<?php

namespace App\Services\SchoolYears;

use App\Models\Configuration;
use App\Models\SchoolYear;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class SchoolYearContextService
{
    public function __construct(private SchoolYearResolver $resolver)
    {
    }

    public function currentSchoolYear(?string $requested = null): string
    {
        $requested = trim((string) $requested);
        if ($requested !== '') {
            return $requested;
        }

        $current = trim((string) (Configuration::getConfig('school_year') ?? ''));
        if ($current !== '') {
            return $current;
        }

        if (Schema::hasTable('school_years')) {
            $year = SchoolYear::query()->where('is_current', true)->orderByDesc('id')->first();
            if ($year && trim((string) $year->name) !== '') {
                return (string) $year->name;
            }
        }

        return '';
    }

    public function currentSemester(?string $requested = null): string
    {
        $requested = trim((string) $requested);
        if ($requested !== '') {
            return $requested;
        }

        return trim((string) (Configuration::getConfig('semester') ?? ''));
    }

    public function options(?string $selectedSchoolYear = null, ?string $selectedSemester = null): array
    {
        if (Schema::hasTable('school_years')) {
            $this->resolver->ensureCurrentTracked();
        }

        $currentSchoolYear = $this->currentSchoolYear($selectedSchoolYear);
        $currentSemester = $this->currentSemester($selectedSemester);

        $schoolYears = $this->schoolYears($currentSchoolYear);
        $semesters = $this->semesters($currentSemester);

        return [
            'school_year' => $currentSchoolYear !== '' ? $currentSchoolYear : null,
            'current_school_year' => $currentSchoolYear !== '' ? $currentSchoolYear : null,
            'semester' => $currentSemester !== '' ? $currentSemester : null,
            'current_semester' => $currentSemester !== '' ? $currentSemester : null,
            'school_years' => $schoolYears,
            'semesters' => $semesters,
        ];
    }

    public function schoolYears(?string $include = null): array
    {
        $years = [];

        if (Schema::hasTable('school_years')) {
            $years = SchoolYear::query()
                ->orderByDesc('start_date')
                ->orderByDesc('id')
                ->get()
                ->map(fn (SchoolYear $year) => [
                    'id' => (int) $year->id,
                    'name' => (string) $year->name,
                    'label' => (string) $year->name,
                    'start_date' => $year->start_date ? $year->start_date->format('Y-m-d') : null,
                    'end_date' => $year->end_date ? $year->end_date->format('Y-m-d') : null,
                    'status' => (string) $year->status,
                    'is_current' => (bool) $year->is_current,
                    'is_editable' => $year->status === SchoolYear::STATUS_ACTIVE,
                ])
                ->all();
        }

        $seen = [];
        foreach ($years as $row) {
            $seen[$row['name']] = true;
        }

        foreach ($this->legacySchoolYearNames() as $name) {
            if (!isset($seen[$name])) {
                $years[] = [
                    'id' => null,
                    'name' => $name,
                    'label' => $name,
                    'start_date' => null,
                    'end_date' => null,
                    'status' => 'legacy',
                    'is_current' => false,
                    'is_editable' => true,
                ];
                $seen[$name] = true;
            }
        }

        $include = trim((string) $include);
        if ($include !== '' && !isset($seen[$include])) {
            array_unshift($years, [
                'id' => null,
                'name' => $include,
                'label' => $include,
                'start_date' => null,
                'end_date' => null,
                'status' => 'selected',
                'is_current' => true,
                'is_editable' => true,
            ]);
        }

        return $years;
    }

    public function semesters(?string $include = null): array
    {
        $names = ['Fall', 'Spring'];
        $current = trim((string) $include);
        if ($current !== '' && !in_array($current, $names, true)) {
            array_unshift($names, $current);
        }

        return array_map(fn (string $name) => [
            'name' => $name,
            'label' => $name,
            'is_current' => $current !== '' && strcasecmp($name, $current) === 0,
        ], $names);
    }

    private function legacySchoolYearNames(): array
    {
        $tables = [
            'students', 'parents', 'users', 'staff', 'student_class', 'teacher_class',
            'events', 'calendar_events', 'scan_log', 'exam_drafts', 'inventory_items',
            'inventory_movements', 'certificate_records', 'semester_scores', 'final_scores',
            'student_decisions', 'below_sixty_decisions', 'whatsapp_group_links',
        ];

        $names = [];
        foreach ($tables as $table) {
            if (!Schema::hasTable($table) || !Schema::hasColumn($table, 'school_year')) {
                continue;
            }

            try {
                $rows = DB::table($table)
                    ->whereNotNull('school_year')
                    ->where('school_year', '!=', '')
                    ->distinct()
                    ->orderByDesc('school_year')
                    ->limit(20)
                    ->pluck('school_year')
                    ->all();
            } catch (\Throwable $e) {
                continue;
            }

            foreach ($rows as $row) {
                $name = trim((string) $row);
                if ($name !== '') {
                    $names[$name] = true;
                }
            }
        }

        $configured = trim((string) (Configuration::getConfig('school_year') ?? ''));
        if ($configured !== '') {
            $names[$configured] = true;
        }

        $out = array_keys($names);
        rsort($out, SORT_NATURAL);

        return $out;
    }
}
