<?php

namespace App\Services\Attendance;

use App\Models\Configuration;
use Carbon\Carbon;

class SemesterRangeService
{
    public function normalizeSemester(?string $semester): string
    {
        $value = strtolower(trim((string)$semester));

        return match ($value) {
            'fall', 'autumn' => 'Fall',
            'spring' => 'Spring',
            default => '',
        };
    }

    public function getSchoolYearRange(string $schoolYear): array
    {
        $config = $this->ensureAttendanceConfigs($schoolYear);

        return [
            Carbon::parse($config['fall_semester_start'])->toDateString(),
            Carbon::parse($config['last_school_day'])->toDateString(),
        ];
    }

    public function getSemesterRange(string $schoolYear, string $semester): ?array
    {
        $semester = $this->normalizeSemester($semester);
        $config = $this->ensureAttendanceConfigs($schoolYear);
        $fallStart = $config['fall_semester_start'];
        $springStart = $config['spring_semester_start'];
        $lastDay = $config['last_school_day'];

        if ($semester === 'Fall' && $fallStart && $springStart) {
            return [
                Carbon::parse($fallStart)->toDateString(),
                Carbon::parse($springStart)->subDay()->toDateString(),
            ];
        }

        if ($semester === 'Spring' && $springStart && $lastDay) {
            return [
                Carbon::parse($springStart)->toDateString(),
                Carbon::parse($lastDay)->toDateString(),
            ];
        }

        return null;
    }

    public function buildSundayList(string $startDate, string $endDate): array
    {
        $start = Carbon::parse($startDate)->startOfDay();
        $end = Carbon::parse($endDate)->startOfDay();

        if ($start->dayOfWeek !== Carbon::SUNDAY) {
            $start = $start->next(Carbon::SUNDAY);
        }

        $dates = [];
        $cursor = $start->copy();

        while ($cursor->lte($end)) {
            $dates[] = $cursor->toDateString();
            $cursor->addWeek();
        }

        return $dates;
    }

    protected function parseSchoolYear(string $schoolYear): array
    {
        if (preg_match('/^\s*(\d{4})\s*-\s*(\d{4})\s*$/', $schoolYear, $m)) {
            return [(int)$m[1], (int)$m[2]];
        }

        $configured = trim((string) Configuration::getConfig('school_year'));
        if (preg_match('/^\s*(\d{4})\s*-\s*(\d{4})\s*$/', $configured, $m)) {
            return [(int) $m[1], (int) $m[2]];
        }

        $year = (int) date('Y');
        $derived = $year . '-' . ($year + 1);
        Configuration::setConfigValueByKey('school_year', $derived);

        return [$year, $year + 1];
    }

    /**
     * Ensure the attendance range config keys exist in `configuration`.
     *
     * @return array{
     *   school_year:string,
     *   fall_semester_start:string,
     *   spring_semester_start:string,
     *   last_school_day:string
     * }
     */
    protected function ensureAttendanceConfigs(string $schoolYear): array
    {
        [$startYear, $endYear] = $this->parseSchoolYear($schoolYear);

        $resolvedSchoolYear = trim($schoolYear);
        if ($resolvedSchoolYear === '') {
            $resolvedSchoolYear = sprintf('%04d-%04d', $startYear, $endYear);
        }

        $defaults = [
            'school_year' => $resolvedSchoolYear,
            'fall_semester_start' => Carbon::create($startYear, 9, 1)->toDateString(),
            'spring_semester_start' => Carbon::create($endYear, 1, 25)->toDateString(),
            'last_school_day' => Carbon::create($endYear, 5, 31)->toDateString(),
        ];

        $resolved = [];
        foreach ($defaults as $key => $defaultValue) {
            $value = trim((string) Configuration::getConfig($key));
            if ($value === '') {
                Configuration::setConfigValueByKey($key, $defaultValue);
                $value = $defaultValue;
            }
            $resolved[$key] = $value;
        }

        return $resolved;
    }
}
