<?php

namespace App\Services\Administrator;

use App\Models\ClassSection;
use App\Models\Enrollment;
use App\Models\Student;
use App\Models\StudentClass;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class AdministratorEnrollmentQueryService
{
    public function __construct(
        protected AdministratorSharedService $shared,
        protected Student $studentModel,
        protected StudentClass $studentClassModel,
        protected Enrollment $enrollmentModel,
        protected ClassSection $classSectionModel,
    ) {
    }

    public function enrollmentWithdrawalData(?string $selectedYear = null): array
    {
        $selectedYear = trim((string) ($selectedYear ?: $this->shared->getSchoolYear()));

        $schoolYears = DB::table('enrollments')
            ->distinct()
            ->orderByDesc('school_year')
            ->pluck('school_year')
            ->map(fn ($year) => (string) $year)
            ->filter()
            ->values()
            ->all();

        $students = method_exists($this->studentModel, 'getStudentsWithClassAndEnrollment')
            ? ($this->studentModel->getStudentsWithClassAndEnrollment() ?? [])
            : [];

        $selectedStartYear = $this->shared->getSchoolYearStartYear($selectedYear);
        $removedPriorIds = [];

        if ($selectedStartYear !== null) {
            $removedRows = DB::table('enrollments')
                ->select('student_id', 'school_year')
                ->where('is_withdrawn', 1)
                ->get();

            foreach ($removedRows as $row) {
                $rowYear = $this->shared->getSchoolYearStartYear((string) ($row->school_year ?? ''));
                if ($rowYear !== null && $rowYear < $selectedStartYear) {
                    $removedPriorIds[(int) ($row->student_id ?? 0)] = true;
                }
            }
        }

        foreach ($students as &$s) {
            $studentId = (int) ($s['id'] ?? 0);
            $s['student_id'] = $studentId;
            $s['removed_previous_year'] = isset($removedPriorIds[$studentId]) ? 'Yes' : 'No';

            if (empty($s['parent_id']) && !empty($s['secondparent_user_id'])) {
                $s['parent_id'] = (int) $s['secondparent_user_id'];
            } else {
                $s['parent_id'] = (int) ($s['parent_id'] ?? 0);
            }

            $pf = trim((string) ($s['parent_firstname'] ?? ''));
            $pl = trim((string) ($s['parent_lastname'] ?? ''));

            if ($pf === '' && $pl === '' && !empty($s['parent_fullname'])) {
                $parts = preg_split('/\s+/', trim((string) $s['parent_fullname']), 2);
                $pf = $parts[0] ?? '';
                $pl = $parts[1] ?? '';
            }

            $s['parent_label'] = trim($pf . ' ' . $pl) ?: 'Unknown Parent';
            $s['parent_sort'] = trim(($pl !== '' ? $pl : $pf) . ' ' . $pf) ?: 'ZZZ Unknown Parent';

            $s['is_new'] = (int) ($s['is_new'] ?? 0);
            $s['new_student'] = $s['is_new'] === 1 ? 'Yes' : 'No';

            $statusForYear = method_exists($this->enrollmentModel, 'getEnrollmentStatus')
                ? $this->enrollmentModel->getEnrollmentStatus($studentId, $selectedYear)
                : null;

            if (!empty($statusForYear)) {
                $s['enrollment_status'] = $statusForYear;
            } elseif (($s['admission_status'] ?? null) === 'denied') {
                $s['enrollment_status'] = 'denied';
            }

            $className = method_exists($this->studentClassModel, 'getClassSectionsByStudentId')
                ? $this->studentClassModel->getClassSectionsByStudentId($studentId, $selectedYear)
                : null;

            $s['class_section'] = $className ?: 'Class not Assigned';

            $s['registration_date_order'] = !empty($s['registration_date'])
                ? Carbon::parse($s['registration_date'])->format('Y-m-d')
                : '';
        }
        unset($s);

        usort($students, function (array $a, array $b) {
            $pa = $a['parent_sort'] ?? '';
            $pb = $b['parent_sort'] ?? '';

            if (strcasecmp($pa, $pb) === 0) {
                $la = $a['lastname'] ?? '';
                $lb = $b['lastname'] ?? '';
                $cmp = strcasecmp($la, $lb);
                if ($cmp !== 0) {
                    return $cmp;
                }

                return strcasecmp($a['firstname'] ?? '', $b['firstname'] ?? '');
            }

            return strcasecmp($pa, $pb);
        });

        $classes = ClassSection::query()
            ->select('id', 'class_section_id', 'class_section_name', 'school_year', 'semester')
            ->where('school_year', $selectedYear)
            ->where('semester', $this->shared->getSemester())
            ->orderBy('class_section_name')
            ->get()
            ->toArray();

        if (empty($classes)) {
            $classes = ClassSection::query()
                ->select('id', 'class_section_id', 'class_section_name')
                ->orderBy('class_section_name')
                ->get()
                ->toArray();
        }

        return [
            'students' => $students,
            'classes' => $classes,
            'semester' => $this->shared->getSemester(),
            'school_year' => $selectedYear,
            'schoolYears' => $schoolYears,
        ];
    }

    public function newStudentsData(): array
    {
        $schoolYear = $this->shared->getSchoolYear();

        $rows = method_exists($this->studentModel, 'getStudentsWithParentsAndEmergency')
            ? ($this->studentModel->getStudentsWithParentsAndEmergency($schoolYear) ?? [])
            : [];

        $newStudents = [];

        foreach ($rows as $r) {
            $studentId = (int) ($r['id'] ?? 0);

            $classSection = method_exists($this->studentClassModel, 'getClassSectionsByStudentId')
                ? $this->studentClassModel->getClassSectionsByStudentId($studentId, $schoolYear)
                : null;

            $enrollmentStatus = method_exists($this->enrollmentModel, 'getEnrollmentStatus')
                ? $this->enrollmentModel->getEnrollmentStatus($studentId, $schoolYear)
                : null;

            $r['class_section'] = $classSection && trim((string) $classSection) !== ''
                ? $classSection
                : 'Class not Assigned';

            $r['is_new'] = (int) ($r['is_new'] ?? 0);
            $r['new_student'] = $r['is_new'] === 1 ? 'Yes' : 'No';
            $r['modalIdContact'] = 'contact_' . $studentId;
            $r['enrollment_status'] = $enrollmentStatus;

            if (!empty($r['registration_date'])) {
                try {
                    $r['registration_date'] = Carbon::parse($r['registration_date'])->format('Y-m-d');
                } catch (\Throwable) {
                    $r['registration_date'] = '';
                }
            }

            $newStudents[] = $r;
        }

        return [
            'new_students' => $newStudents,
            'total_new' => count($newStudents),
        ];
    }
}