<?php

namespace App\Services\Invoices;

use App\Models\Enrollment;
use App\Models\Invoice;
use App\Models\Student;
use App\Models\StudentClass;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class InvoiceManagementService
{
    public function __construct(private InvoiceConfigService $config)
    {
    }

    public function getManagementData(?string $schoolYear): array
    {
        $schoolYear = trim((string) ($schoolYear ?? ''));
        if ($schoolYear === '') {
            $schoolYear = $this->config->getSchoolYear();
        }

        $schoolYears = DB::table('invoices')
            ->select('school_year')
            ->distinct()
            ->orderBy('school_year', 'DESC')
            ->pluck('school_year')
            ->map(fn ($val) => (string) $val)
            ->filter(fn ($val) => $val !== '')
            ->values()
            ->all();

        if (empty($schoolYears)) {
            $schoolYears = [$schoolYear];
        }

        $invoiceData = [];
        $parents = User::getUsersByRoleAndSchoolYear('parent', $schoolYear);

        foreach ($parents as $parent) {
            $students = Student::query()
                ->where('parent_id', $parent['id'])
                ->get()
                ->map(fn ($r) => $r->toArray())
                ->all();

            $parentData = [
                'parent_name' => trim(($parent['firstname'] ?? '') . ' ' . ($parent['lastname'] ?? '')),
                'parent_id' => (int) $parent['id'],
                'enrolledKids' => [],
                'withdrawnKids' => [],
                'invoice_amount' => 0,
                'refund_amount' => 0,
                'last_updated' => null,
                'invoice_date' => null,
                'invoice_id' => null,
            ];

            $invoices = Invoice::getInvoicesByParentId((int) $parent['id'], $schoolYear);
            foreach ($invoices as $invoice) {
                if (!$invoice) {
                    continue;
                }

                $parentData['invoice_amount'] = (float) ($invoice['total_amount'] ?? 0);
                $parentData['last_updated'] = $invoice['updated_at'] ?? null;
                $parentData['invoice_id'] = $invoice['id'] ?? null;

                if (!empty($invoice['issue_date'])) {
                    $tzName = $this->config->getTimezone();
                    $parentData['invoice_date'] = (new \DateTimeImmutable($invoice['issue_date'], new \DateTimeZone('UTC')))
                        ->setTimezone(new \DateTimeZone($tzName))
                        ->format('Y-m-d H:i:s');
                } else {
                    $parentData['invoice_date'] = !empty($invoice['updated_at'])
                        ? date('Y-m-d H:i:s', strtotime($invoice['updated_at']))
                        : null;
                }

                $refund = DB::table('refunds')
                    ->selectRaw('COALESCE(SUM(refund_paid_amount),0) AS refund_paid_amount')
                    ->where('parent_id', $parent['id'])
                    ->where('school_year', $schoolYear)
                    ->whereIn('status', ['Partial', 'Paid'])
                    ->first();

                $parentData['refund_amount'] = (float) ($refund->refund_paid_amount ?? 0.0);
                break;
            }

            foreach ($students as $student) {
                $grade = 'N/A';
                $studentClass = DB::table('student_class')
                    ->where('student_id', $student['id'])
                    ->where('school_year', $schoolYear)
                    ->first();

                if ($studentClass && isset($studentClass->class_section_id)) {
                    $classSection = DB::table('classSection')
                        ->where('class_section_id', $studentClass->class_section_id)
                        ->first();
                    if ($classSection && isset($classSection->class_section_name)) {
                        $grade = $classSection->class_section_name;
                    }
                }

                $enrollments = Enrollment::query()
                    ->where('student_id', $student['id'])
                    ->where('school_year', $schoolYear)
                    ->get()
                    ->map(fn ($r) => $r->toArray())
                    ->all();

                foreach ($enrollments as $enrollment) {
                    $kid = [
                        'name' => trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? '')),
                        'grade' => $grade,
                        'tuition_fee' => (float) ($enrollment['tuition_fee'] ?? 0),
                    ];

                    switch ($enrollment['enrollment_status']) {
                        case 'payment pending':
                        case 'enrolled':
                            $parentData['enrolledKids'][] = $kid;
                            break;
                        case 'withdraw under review':
                        case 'withdrawn':
                        case 'refund pending':
                            $parentData['withdrawnKids'][] = $kid;
                            break;
                        default:
                            break;
                    }
                }
            }

            if (!empty($parentData['enrolledKids']) || !empty($parentData['withdrawnKids'])) {
                $invoiceData[] = $parentData;
            }
        }

        return [
            'schoolYear' => $schoolYear,
            'schoolYears' => $schoolYears,
            'invoices' => $invoiceData,
        ];
    }
}
