<?php

namespace App\Modules\HR\Recruitment\Services;

use App\Modules\HR\Employees\Models\Employee;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingCase;
use App\Modules\HR\Recruitment\Repositories\RecruitmentOnboardingCaseRepository;
use App\Modules\HR\Recruitment\Repositories\RecruitmentOnboardingTaskRepository;
use App\Modules\HR\Recruitment\Support\OnboardingCaseStatus;
use App\Modules\HR\Recruitment\Support\OnboardingTaskStatus;

class OnboardingProgressService
{
    public function __construct(
        private readonly RecruitmentOnboardingCaseRepository $cases,
        private readonly RecruitmentOnboardingTaskRepository $tasks,
    ) {}

    public function recalculate(RecruitmentOnboardingCase $case, ?int $actorId = null): RecruitmentOnboardingCase
    {
        $required = $this->tasks->requiredForCase((int) $case->id);
        $total = $required->count();
        $done = $required->filter(
            fn ($t) => in_array((string) $t->status, OnboardingTaskStatus::doneLike(), true)
        )->count();

        $percent = $total === 0 ? 100 : (int) round(($done / $total) * 100);
        $payload = ['progress_percent' => $percent];

        if ($percent >= 100 && $case->status !== OnboardingCaseStatus::CANCELLED) {
            $payload = array_merge($payload, $this->completionPayload($case, $actorId));
            $this->markEmployeeCompleted((int) $case->employee_id);
        } elseif ($case->status === OnboardingCaseStatus::COMPLETED && $percent < 100) {
            $payload['status'] = OnboardingCaseStatus::IN_PROGRESS;
            $payload['completed_at'] = null;
            $payload['completed_by'] = null;
            $this->clearEmployeeCompleted((int) $case->employee_id);
        }

        return $this->cases->update($case, $payload);
    }

    /** @return array<string, mixed> */
    private function completionPayload(RecruitmentOnboardingCase $case, ?int $actorId): array
    {
        if ($case->status === OnboardingCaseStatus::COMPLETED) {
            return ['status' => OnboardingCaseStatus::COMPLETED];
        }

        return [
            'status' => OnboardingCaseStatus::COMPLETED,
            'completed_at' => now(),
            'completed_by' => $actorId,
        ];
    }

    private function markEmployeeCompleted(int $employeeId): void
    {
        Employee::query()->whereKey($employeeId)->update([
            'onboarding_completed_at' => now(),
        ]);
    }

    private function clearEmployeeCompleted(int $employeeId): void
    {
        Employee::query()->whereKey($employeeId)->update([
            'onboarding_completed_at' => null,
        ]);
    }
}
