<?php

namespace App\Services;

use App\Services\Semesters\SemesterConfigService;
use DateTimeImmutable;

class SemesterRangeService
{
    public function __construct(private SemesterConfigService $configService)
    {
    }

    public function getSchoolYearRange(string $schoolYear): array
    {
        $start = $this->configService->getFallStart();
        $end = $this->configService->getLastSchoolDay();

        if ($start === null || $end === null) {
            [$fallbackStart, $fallbackEnd] = $this->fallbackSchoolYearRange($schoolYear);
            $start ??= $fallbackStart;
            $end ??= $fallbackEnd;
        }

        if ($end < $start) {
            [$start, $end] = [$end, $start];
        }

        return [$start->format('Y-m-d'), $end->format('Y-m-d')];
    }

    public function getSemesterRange(string $schoolYear, string $semester): ?array
    {
        if (!preg_match('/^(\\d{4})-(\\d{4})$/', $schoolYear, $m)) {
            return null;
        }
        $y1 = (int) $m[1];
        $y2 = (int) $m[2];

        $normalized = ucfirst(strtolower(trim($semester)));
        if ($normalized === 'Fall') {
            return [sprintf('%04d-09-21', $y1), sprintf('%04d-01-18', $y2)];
        }
        if ($normalized === 'Spring') {
            return [sprintf('%04d-01-25', $y2), sprintf('%04d-05-31', $y2)];
        }

        return null;
    }

    public function normalizeSemester(?string $semester): string
    {
        $value = strtolower(trim((string) ($semester ?? '')));
        if ($value === 'fall') {
            return 'Fall';
        }
        if ($value === 'spring') {
            return 'Spring';
        }
        return '';
    }

    public function getSemesterForDate(?string $date = null): string
    {
        $fallStart = $this->configService->getFallStart();
        $springStart = $this->configService->getSpringStart();
        $lastDay = $this->configService->getLastSchoolDay();

        try {
            $target = new DateTimeImmutable($date ?: 'now');
        } catch (\Throwable) {
            return '';
        }

        if ($fallStart === null || $springStart === null || $lastDay === null) {
            return '';
        }

        $target = $target->setTime(0, 0, 0);
        $fallStart = $fallStart->setTime(0, 0, 0);
        $springStart = $springStart->setTime(0, 0, 0);
        $lastDay = $lastDay->setTime(0, 0, 0);

        $nextFallStart = $fallStart <= $lastDay ? $fallStart->modify('+1 year') : $fallStart;

        if (($fallStart <= $target && $target < $springStart)
            || ($lastDay <= $target && $target < $nextFallStart)
        ) {
            return 'Fall';
        }

        if ($springStart <= $target && $target < $lastDay) {
            return 'Spring';
        }

        return '';
    }

    private function fallbackSchoolYearRange(string $schoolYear): array
    {
        if (preg_match('/^(\\d{4})-(\\d{4})$/', $schoolYear, $m)) {
            $y1 = (int) $m[1];
            $y2 = (int) $m[2];
            return [new DateTimeImmutable($y1 . '-09-01'), new DateTimeImmutable($y2 . '-06-30')];
        }

        $currentYear = (int) date('Y');
        return [
            new DateTimeImmutable($currentYear . '-09-01'),
            new DateTimeImmutable(($currentYear + 1) . '-06-30'),
        ];
    }
}
