<?php

namespace App\Modules\HR\Recruitment\Services;

use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingAttachment;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingTask;
use App\Modules\HR\Recruitment\Repositories\RecruitmentOnboardingTaskRepository;
use App\Modules\HR\Recruitment\Support\OnboardingTaskStatus;
use Illuminate\Http\UploadedFile;
use Illuminate\Validation\ValidationException;

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

    /**
     * @param  array{
     *     status?: string,
     *     assigned_to?: ?int,
     *     due_date?: ?string,
     *     notes?: ?string,
     *     meta?: ?array<string, mixed>
     * }  $data
     */
    public function update(RecruitmentOnboardingTask $task, array $data, int $userId): RecruitmentOnboardingTask
    {
        $case = $task->onboardingCase;
        abort_if($case === null, 404);
        $this->cases->assertNotCancelled($case);

        $payload = $this->buildPayload($task, $data, $userId);
        $updated = $this->tasks->update($task, $payload);
        $this->progress->recalculate($case->fresh(), $userId);

        return $updated->load(['assignee', 'attachments']);
    }

    public function attach(RecruitmentOnboardingTask $task, UploadedFile $file, int $userId): RecruitmentOnboardingAttachment
    {
        $case = $task->onboardingCase;
        abort_if($case === null, 404);
        $this->cases->assertNotCancelled($case);

        $dir = 'tenants/'.$case->tenant_id.'/onboarding/'.$case->id.'/tasks/'.$task->id;
        $path = $file->store($dir, 'local');

        return $this->tasks->createAttachment([
            'tenant_id' => (int) $case->tenant_id,
            'onboarding_task_id' => (int) $task->id,
            'disk' => 'local',
            'path' => $path,
            'original_name' => $file->getClientOriginalName(),
            'mime' => $file->getClientMimeType(),
            'size' => (int) $file->getSize(),
            'uploaded_by' => $userId,
        ]);
    }

    /** @param  array<string, mixed>  $data */
    private function buildPayload(RecruitmentOnboardingTask $task, array $data, int $userId): array
    {
        $payload = [];
        foreach (['assigned_to', 'due_date', 'notes'] as $key) {
            if (array_key_exists($key, $data)) {
                $payload[$key] = $data[$key];
            }
        }
        if (array_key_exists('meta', $data)) {
            $payload['meta'] = array_merge($task->meta ?? [], is_array($data['meta']) ? $data['meta'] : []);
        }
        if (! empty($data['status'])) {
            $status = (string) $data['status'];
            if (! in_array($status, OnboardingTaskStatus::all(), true)) {
                throw ValidationException::withMessages(['status' => ['Invalid status.']]);
            }
            $payload['status'] = $status;
            $payload = array_merge($payload, $this->completionFields($status, $userId, $task));
        }

        return $payload;
    }

    /** @return array<string, mixed> */
    private function completionFields(string $status, int $userId, RecruitmentOnboardingTask $task): array
    {
        if (in_array($status, OnboardingTaskStatus::doneLike(), true)) {
            return [
                'completed_at' => $task->completed_at ?? now(),
                'completed_by' => $task->completed_by ?? $userId,
            ];
        }

        return ['completed_at' => null, 'completed_by' => null];
    }
}
