<?php

namespace App\Services\Hr;

use App\Models\Asset;
use App\Models\FnfSettlement;
use App\Models\Offboarding;
use App\Models\OffboardingChecklistItem;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class OffboardingWorkflowService
{
    public const DEFAULT_CHECKLIST = [
        ['category' => 'manager', 'task_name' => 'Knowledge transfer sign-off', 'description' => 'Manager confirms handover of responsibilities.'],
        ['category' => 'it', 'task_name' => 'Disable system access', 'description' => 'Revoke email, VPN, and application accounts.'],
        ['category' => 'assets', 'task_name' => 'Return assigned assets', 'description' => 'Collect laptop, ID card, and other company assets.'],
        ['category' => 'hr', 'task_name' => 'Exit interview', 'description' => 'Conduct exit interview and document feedback.'],
        ['category' => 'hr', 'task_name' => 'Initiate F&F settlement', 'description' => 'Prepare full and final settlement worksheet.'],
        ['category' => 'finance', 'task_name' => 'Clear advances / loans', 'description' => 'Verify outstanding advances and loan recoveries.'],
        ['category' => 'docs', 'task_name' => 'Relieving letter & experience certificate', 'description' => 'Issue exit documents after clearance.'],
    ];

    public function __construct(
        protected FnfSettlementCalculator $fnfCalculator
    ) {}

    public function initiate(Offboarding $offboarding): Offboarding
    {
        return DB::transaction(function () use ($offboarding) {
            $user = User::withoutGlobalScopes()->findOrFail($offboarding->user_id);
            $lwd = $offboarding->last_working_date ?? $offboarding->offboarding_date;

            $offboarding->update([
                'last_working_date' => $lwd,
                'status' => Offboarding::STATUS_CLEARANCE_PENDING,
            ]);

            if ($lwd) {
                $user->update(['last_working_date' => $lwd]);
            }

            $this->seedChecklist($offboarding);
            $this->seedAssetChecklistItems($offboarding, (int) $user->id);
            $this->fnfCalculator->createDraftFromOffboarding($offboarding->fresh());

            return $offboarding->fresh(['checklistItems', 'fnfSettlement', 'user']);
        });
    }

    public function updateChecklistItem(OffboardingChecklistItem $item, string $status, ?string $notes, int $actorId): OffboardingChecklistItem
    {
        $item->update([
            'status' => $status,
            'notes' => $notes,
            'completed_at' => in_array($status, [
                OffboardingChecklistItem::STATUS_COMPLETED,
                OffboardingChecklistItem::STATUS_WAIVED,
                OffboardingChecklistItem::STATUS_NA,
            ], true) ? now() : null,
            'completed_by' => in_array($status, [
                OffboardingChecklistItem::STATUS_COMPLETED,
                OffboardingChecklistItem::STATUS_WAIVED,
            ], true) ? $actorId : null,
        ]);

        $this->syncOffboardingStatus($item->offboarding->fresh(['checklistItems']));

        return $item->fresh();
    }

    public function syncOffboardingStatus(Offboarding $offboarding): void
    {
        if ($offboarding->status === Offboarding::STATUS_CANCELLED) {
            return;
        }

        if ($offboarding->isClearanceComplete()) {
            $offboarding->update(['status' => Offboarding::STATUS_CLEARED]);

            $fnf = $offboarding->fnfSettlement;
            if ($fnf && $fnf->status === FnfSettlement::STATUS_DRAFT) {
                $fnf->update(['status' => FnfSettlement::STATUS_PENDING_APPROVAL]);
            }

            return;
        }

        if ($offboarding->status === Offboarding::STATUS_CLEARED && ! $offboarding->isClearanceComplete()) {
            $offboarding->update(['status' => Offboarding::STATUS_CLEARANCE_PENDING]);
        }
    }

    protected function seedChecklist(Offboarding $offboarding): void
    {
        if ($offboarding->checklistItems()->exists()) {
            return;
        }

        $order = 0;
        foreach (self::DEFAULT_CHECKLIST as $task) {
            OffboardingChecklistItem::create([
                'company_id' => $offboarding->company_id,
                'offboarding_id' => $offboarding->id,
                'category' => $task['category'],
                'task_name' => $task['task_name'],
                'description' => $task['description'],
                'status' => OffboardingChecklistItem::STATUS_PENDING,
                'display_order' => $order++,
            ]);
        }
    }

    protected function seedAssetChecklistItems(Offboarding $offboarding, int $userId): void
    {
        $assets = Asset::withoutGlobalScopes()
            ->where('company_id', $offboarding->company_id)
            ->where('assigned_to', $userId)
            ->where('status', 'assigned')
            ->get();

        if ($assets->isEmpty()) {
            return;
        }

        $maxOrder = (int) $offboarding->checklistItems()->max('display_order');

        foreach ($assets as $asset) {
            $exists = $offboarding->checklistItems()
                ->where('category', 'assets')
                ->where('task_name', 'Return: ' . $asset->name)
                ->exists();

            if ($exists) {
                continue;
            }

            OffboardingChecklistItem::create([
                'company_id' => $offboarding->company_id,
                'offboarding_id' => $offboarding->id,
                'category' => 'assets',
                'task_name' => 'Return: ' . $asset->name,
                'description' => 'Serial: ' . ($asset->serial_number ?: '—'),
                'status' => OffboardingChecklistItem::STATUS_PENDING,
                'display_order' => ++$maxOrder,
            ]);
        }
    }
}
