<?php

namespace App\Services;

use App\DTOs\Excul\ListExculRequest;
use App\Enums\IzinStatus;
use App\Models\Tdaftarexcul;
use App\Models\Tkelsis1;
use App\Repositories\ExculApprovalRepository;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

final class ExculApprovalService
{
    public function __construct(
        private readonly ExculApprovalRepository $repo,
        private readonly ExculCacheService       $cache,
    ) {}

    public function list(ListExculRequest $dto): LengthAwarePaginator
    {
        return $this->cache->getList(
            $dto->cacheKey(),
            fn () => $this->repo->paginated($dto),
        );
    }

    public function stats(): array
    {
        return $this->cache->getStats(
            fn () => $this->repo->statCounts(),
        );
    }

    public function approve(int $id): Tdaftarexcul
    {
        $daftar = $this->repo->findOrFail($id);

        if ($daftar->sta !== IzinStatus::PENDING) {
            throw ValidationException::withMessages([
                'sta' => 'Pendaftaran sudah diproses sebelumnya.',
            ]);
        }

        DB::transaction(function () use ($daftar) {
            $daftar->sta = IzinStatus::APPROVED;
            $daftar->save();

            Tkelsis1::updateOrCreate(
                [
                    'ids'   => $daftar->idsis,
                    'idkel' => $daftar->idkel,
                ],
                [
                    'tin'   => $daftar->tin,
                    'idta'  => $daftar->idta,
                    'idmen' => 263,
                    'idtra' => random_int(1, 999),
                    'sta'   => 0,
                ]
            );
        });

        $this->cache->invalidateStats();
        $this->cache->invalidateList();

        return $daftar->fresh();
    }

    public function reject(int $id, ?string $alasan): Tdaftarexcul
    {
        $daftar = $this->repo->findOrFail($id);

        if ($daftar->sta !== IzinStatus::PENDING) {
            throw ValidationException::withMessages([
                'sta' => 'Pendaftaran sudah diproses sebelumnya.',
            ]);
        }

        DB::transaction(function () use ($daftar, $alasan) {
            $daftar->sta = IzinStatus::REJECTED;
            $daftar->ala = $alasan;
            $daftar->save();
        });

        $this->cache->invalidateStats();
        $this->cache->invalidateList();

        return $daftar->fresh();
    }
}