<?php

declare(strict_types=1);

namespace Maestro\Core\Modules\HourRegistration\Services;

use Illuminate\Contracts\Auth\Authenticatable;
use Maestro\Core\Modules\Customers\Models\Customer;
use Maestro\Core\Modules\HourRegistration\Enums\HourRegistrationType;
use Maestro\Core\Modules\HourRegistration\Models\HourProject;
use Maestro\Core\Modules\HourRegistration\Models\HourTimesheetLine;

final class HourApproverResolver
{
    public function resolveApproverUserId(HourTimesheetLine $line): ?int
    {
        $line->loadMissing(['customer', 'hourProject', 'hourTask.project', 'hourTask']);

        return match ($line->registration_type) {
            HourRegistrationType::Internal => null,
            HourRegistrationType::Customer => $this->customerApproverId($line),
            HourRegistrationType::Project => $line->hourProject?->project_lead_id,
            HourRegistrationType::Task => $this->taskApproverId($line),
        };
    }

    public function lineRequiresLeadApproval(HourTimesheetLine $line): bool
    {
        return $line->registration_type !== HourRegistrationType::Internal;
    }

    private function customerApproverId(HourTimesheetLine $line): ?int
    {
        /** @var Customer|null $c */
        $c = $line->customer;

        return $c?->project_manager_id;
    }

    private function taskApproverId(HourTimesheetLine $line): ?int
    {
        $task = $line->hourTask;
        if ($task === null) {
            return null;
        }

        if ($task->override_lead_id !== null) {
            return $task->override_lead_id;
        }

        /** @var HourProject|null $p */
        $p = $task->project;

        return $p?->project_lead_id;
    }

    /** True when the authenticated user may approve/reject this line (if pending). */
    public function userCanApproveLine(HourTimesheetLine $line, int $userId): bool
    {
        $expected = $this->resolveApproverUserId($line);

        return $expected !== null && $expected === $userId;
    }

    public function actingUserMayApprove(?Authenticatable $user, HourTimesheetLine $line): bool
    {
        if ($user === null || ! method_exists($user, 'getAuthIdentifier')) {
            return false;
        }

        if (method_exists($user, 'can') && $user->can('hours.admin')) {
            return true;
        }

        return $this->userCanApproveLine($line, (int) $user->getAuthIdentifier());
    }
}
