<?php

namespace App\Services\Admin\Master;

use App\Models\AcademicTerm;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class AcademicTermService
{
    public function paginated(int $perPage = 25, string $search = '', ?string $semester = null, ?bool $isActive = null): LengthAwarePaginator
    {
        return AcademicTerm::query()
            ->when($search, fn ($q) => $q->where('academic_year', 'like', "%{$search}%"))
            ->when($semester, fn ($q) => $q->where('semester', $semester))
            ->when($isActive !== null, fn ($q) => $q->where('is_active', $isActive))
            ->latest()
            ->paginate($perPage, ['id', 'academic_year', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters']);
    }

    public function create(array $data): AcademicTerm
    {
        return AcademicTerm::create([
            ...$data,
            'open_semesters' => $this->normalizeOpenSemesters($data['open_semesters'] ?? []),
        ]);
    }

    public function update(AcademicTerm $academicTerm, array $data): AcademicTerm
    {
        $academicTerm->update([
            'academic_year' => $data['academic_year'],
            'semester' => $data['semester'],
            'start_date' => $data['start_date'],
            'end_date' => $data['end_date'],
            'is_active' => $data['is_active'],
            'open_semesters' => $this->normalizeOpenSemesters($data['open_semesters'] ?? []),
        ]);

        return $academicTerm;
    }

    public function delete(AcademicTerm $academicTerm): bool
    {
        return $academicTerm->delete();
    }

    public function updateActiveStatus(AcademicTerm $academicTerm, bool $isActive): void
    {
        DB::transaction(function () use ($academicTerm, $isActive) {
            if ($isActive) {
                AcademicTerm::where('id', '!=', $academicTerm->id)->update(['is_active' => false]);
            }

            $academicTerm->update(['is_active' => $isActive]);
        });
    }

    public function getAllForSelect(): Collection
    {
        return AcademicTerm::latest()->get(['id', 'academic_year', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters']);
    }

    /**
     * The academic term currently marked active, falling back to the one with
     * the latest start date if none is explicitly active.
     */
    public function getActive(): ?AcademicTerm
    {
        return AcademicTerm::where('is_active', true)->first()
            ?? AcademicTerm::orderByDesc('start_date')->first();
    }

    /**
     * @param  array<int, mixed>  $openSemesters
     * @return array<int, int>
     */
    private function normalizeOpenSemesters(array $openSemesters): array
    {
        return array_values(array_unique(array_map('intval', $openSemesters)));
    }
}
