<?php

namespace App\Libraries\Tuition;

use App\Interfaces\TuitionCalculatorInterface;

final class NewTuitionCalculatorService implements TuitionCalculatorInterface
{
    public function calculateFamilyTuition(array $students, array $config): array
    {
        $gradeFee = (int) ($config['grade_fee'] ?? 9);
        $fullAmountCents = $this->toCents($config['new_tuition_full_amount'] ?? 370);
        $youthAmountCents = $this->toCents($config['new_tuition_youth_amount'] ?? $config['youth_fee'] ?? 200);
        $secondDiscountCents = $this->toCents($config['new_tuition_second_student_discount'] ?? 50);
        $thirdDiscountCents = $this->toCents($config['new_tuition_third_student_discount'] ?? 50);
        $fourthPlusDiscountCents = $this->toCents($config['new_tuition_fourth_plus_discount'] ?? 100);

        usort($students, function (array $left, array $right) use ($gradeFee): int {
            $leftLevel = GradeLevelParser::parse($left['grade_level'] ?? null, $gradeFee);
            $rightLevel = GradeLevelParser::parse($right['grade_level'] ?? null, $gradeFee);

            return [$leftLevel, (int) ($left['student_id'] ?? 0)] <=> [$rightLevel, (int) ($right['student_id'] ?? 0)];
        });

        $details = [];
        $regularPosition = 0;

        foreach (array_values($students) as $student) {
            $level = GradeLevelParser::parse($student['grade_level'] ?? null, $gradeFee);

            if ($level > $gradeFee) {
                $position = null;
                $discountCents = 0;
                $rule = 'new_youth_unit_price';
                $baseAmountCents = $youthAmountCents;
            } else {
                $regularPosition++;
                $position = $regularPosition;

                if ($position === 1) {
                    $discountCents = 0;
                    $rule = 'new_first_student_full_amount';
                } elseif ($position === 2) {
                    $discountCents = $secondDiscountCents;
                    $rule = 'new_second_student_discount';
                } elseif ($position === 3) {
                    $discountCents = $thirdDiscountCents;
                    $rule = 'new_third_student_discount';
                } else {
                    $discountCents = $fourthPlusDiscountCents;
                    $rule = 'new_fourth_plus_student_discount';
                }

                $baseAmountCents = $fullAmountCents;
            }

            $amountCents = max(0, $baseAmountCents - $discountCents);

            $details[] = [
                'student_id' => (int) ($student['student_id'] ?? 0),
                'student_name' => (string) ($student['student_name'] ?? ''),
                'grade_level' => $student['grade_level'] ?? null,
                'family_position' => $position,
                'full_amount' => $this->fromCents($baseAmountCents),
                'discount' => $this->fromCents($discountCents),
                'rule' => $rule,
                'amount' => $this->fromCents($amountCents),
            ];
        }

        $total = array_sum(array_map(fn (array $detail): int => $this->toCents($detail['amount']), $details));

        return [
            'calculator' => 'new',
            'total' => $this->fromCents($total),
            'details' => $details,
        ];
    }

    private function toCents($amount): int
    {
        return (int) round(((float) $amount) * 100);
    }

    private function fromCents(int $cents): string
    {
        return number_format($cents / 100, 2, '.', '');
    }
}
