<?php

namespace App\Services;

use App\Enums\ApprovalStatus;
use App\Enums\TravelStatus;
use App\Jobs\SendApprovalDecisionEmail;
use App\Jobs\SendApprovalRequestEmail;
use App\Models\TravelRequest;
use App\Models\TravelRequestApproval;
use App\Models\User;

class ApprovalService
{
    public function submit(TravelRequest $travelRequest): void
    {
        $workflow = $travelRequest->workflow;

        if (! $workflow) {
            return;
        }

        $steps = $workflow->steps()->orderBy('order')->get();

        foreach ($steps as $index => $step) {
            TravelRequestApproval::create([
                'travel_request_id' => $travelRequest->id,
                'approval_step_id' => $step->id,
                'approver_id' => null,
                'status' => $index === 0 ? ApprovalStatus::Pending->value : null,
                'comments' => null,
                'acted_at' => null,
            ]);
        }

        $travelRequest->update([
            'status' => TravelStatus::Pending,
            'submitted_at' => now(),
        ]);

        SendApprovalRequestEmail::dispatch($travelRequest, $steps->first()->role);
    }

    public function approve(TravelRequestApproval $approval, User $approver, ?string $comments): void
    {
        $approval->update([
            'status' => ApprovalStatus::Approved,
            'approver_id' => $approver->id,
            'comments' => $comments,
            'acted_at' => now(),
        ]);

        $travelRequest = $approval->travelRequest;

        $nextApproval = TravelRequestApproval::query()
            ->where('travel_request_id', $travelRequest->id)
            ->whereNull('status')
            ->with('step')
            ->orderBy('id')
            ->first();

        if ($nextApproval) {
            $nextApproval->update(['status' => ApprovalStatus::Pending->value]);
            SendApprovalRequestEmail::dispatch($travelRequest, $nextApproval->step->role);
        } else {
            $travelRequest->update(['status' => TravelStatus::Approved]);
            SendApprovalDecisionEmail::dispatch($travelRequest);
        }
    }

    public function reject(TravelRequestApproval $approval, User $approver, ?string $comments): void
    {
        $approval->update([
            'status' => ApprovalStatus::Rejected,
            'approver_id' => $approver->id,
            'comments' => $comments,
            'acted_at' => now(),
        ]);

        $approval->travelRequest->update(['status' => TravelStatus::Rejected]);

        SendApprovalDecisionEmail::dispatch($approval->travelRequest);
    }
}
