<?php

namespace App\Services\Invoices;

use App\Models\ClassSection;

class InvoiceTuitionService
{
    public function __construct(
        private InvoiceGradeService $grades,
        private int $gradeFee,
        private float $firstStudentFee,
        private float $secondStudentFee,
        private float $youthFee,
        private string $timezone
    ) {
    }

    public function calculateTuitionFee(array $registeredKids, array $withdrawnKids, ?string $refundDeadline): float
    {
        $refundOk = $this->isRefundAllowed($refundDeadline);
        $tuitionStudents = $refundOk ? $registeredKids : array_merge($registeredKids, $withdrawnKids);

        return $this->calculateTotalTuitionFee($tuitionStudents);
    }

    public function calculateTotalTuitionFee(array $students): float
    {
        foreach ($students as &$student) {
            $gradeName = ClassSection::getClassSectionNameBySectionId($student['class_section_id'] ?? null) ?? '';
            $student['grade'] = strtoupper(trim($gradeName));
        }
        unset($student);

        $regularCount = 0;
        $youthCount = 0;

        foreach ($students as $student) {
            $levelInfo = $this->grades->getGradeLevel($student['grade'] ?? '');
            $level = (int) ($levelInfo['level'] ?? 999);

            if ($level > $this->gradeFee) {
                $youthCount++;
            } else {
                $regularCount++;
            }
        }

        $total = 0.0;
        $total += $youthCount * $this->youthFee;

        if ($regularCount >= 2) {
            $total += $this->firstStudentFee;
            $total += ($regularCount - 1) * $this->secondStudentFee;
        } elseif ($regularCount === 1) {
            $total += $this->firstStudentFee;
        }

        return $total;
    }

    private function isRefundAllowed(?string $refundDeadline): bool
    {
        if (!$refundDeadline) {
            return true;
        }

        try {
            $tz = new \DateTimeZone($this->timezone);
            $today = new \DateTimeImmutable('today', $tz);
            $deadline = new \DateTimeImmutable($refundDeadline, $tz);
            return $today <= $deadline;
        } catch (\Throwable $e) {
            return true;
        }
    }
}
