<?php

namespace App\Services\Students;

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

class StudentDirectoryService
{
    public function __construct(private StudentConfigService $configService)
    {
    }

    public function assignmentData(?string $schoolYear = null): array
    {
        $context = $this->configService->context();
        $schoolYear = $schoolYear ?: (string) ($context['school_year'] ?? '');
        $semester = (string) ($context['semester'] ?? '');

        $yearsRows = DB::table('enrollments')
            ->selectRaw('DISTINCT school_year')
            ->orderByDesc('school_year')
            ->get()
            ->map(fn ($r) => (array) $r)
            ->all();

        $schoolYears = array_values(array_filter(array_map(static function ($r) {
            return isset($r['school_year']) ? (string) $r['school_year'] : null;
        }, $yearsRows)));

        $students = Student::query()
            ->select('students.id', 'students.firstname', 'students.lastname', 'students.registration_date', 'students.is_new', 'students.age', 'students.parent_id', 'students.registration_grade')
            ->join('enrollments as e', 'e.student_id', '=', 'students.id')
            ->when($schoolYear !== '', fn ($q) => $q->where('e.school_year', $schoolYear))
            ->groupBy('students.id')
            ->orderBy('students.lastname')
            ->orderBy('students.firstname')
            ->get()
            ->toArray();

        if (empty($students)) {
            $students = Student::query()
                ->select('students.id', 'students.firstname', 'students.lastname', 'students.registration_date', 'students.is_new', 'students.age', 'students.parent_id', 'students.registration_grade')
                ->orderBy('students.lastname')
                ->orderBy('students.firstname')
                ->get()
                ->toArray();
        }

        $studentData = [];
        foreach ($students as $student) {
            $studentId = (int) ($student['id'] ?? 0);
            $sectionNames = StudentClass::getClassSectionsByStudentIdWithFlags($studentId, $schoolYear, true);
            $sectionIds = StudentClass::getClassSectionIdsByStudentId($studentId, $schoolYear);
            $sectionDisplay = !empty($sectionNames) ? implode(', ', $sectionNames) : '';

            $parentId = (int) ($student['parent_id'] ?? 0);
            $emergencyInfo = $parentId > 0
                ? (EmergencyContact::getEmergencyContactByParentId($parentId) ?? [])
                : [];

            $studentData[] = [
                'student_id' => $studentId,
                'name' => trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? '')),
                'age' => $student['age'] ?? 'N/A',
                'email' => $emergencyInfo['emergency_contact_name'] ?? '',
                'phone' => $emergencyInfo['cellphone'] ?? '',
                'registration_grade' => $student['registration_grade'] ?? 'N/A',
                'class_section_name' => $sectionDisplay !== '' ? $sectionDisplay : 'No class assigned',
                'class_section_names' => $sectionNames,
                'class_section_ids' => $sectionIds,
                'new_student' => ((int) ($student['is_new'] ?? 0) === 1) ? 'Yes' : 'No',
                'registration_date' => $student['registration_date'] ?? '',
                'school_year' => $schoolYear,
                'semester' => $semester,
            ];
        }

        $classes = ClassSection::query()
            ->select('id', 'class_section_id', 'class_section_name', 'school_year')
            ->when($schoolYear !== '', fn ($q) => $q->where('school_year', $schoolYear))
            ->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' => $studentData,
            'classes' => $classes,
            'schoolYears' => $schoolYears,
            'selectedYear' => $schoolYear,
            'currentYear' => (string) ($context['school_year'] ?? ''),
            'isCurrentYear' => $schoolYear !== '' && $schoolYear === (string) ($context['school_year'] ?? ''),
        ];
    }

    public function removedStudents(?string $schoolYear = null): array
    {
        $context = $this->configService->context();
        $schoolYear = $schoolYear ?: (string) ($context['school_year'] ?? '');

        $activeStudents = Student::query()
            ->select('id', 'school_id', 'firstname', 'lastname', 'gender', 'age')
            ->where('is_active', 1)
            ->orderBy('lastname')
            ->orderBy('firstname')
            ->get()
            ->toArray();

        $removedStudents = Student::query()
            ->select('id', 'school_id', 'firstname', 'lastname', 'gender', 'age')
            ->where('is_active', 0)
            ->orderBy('lastname')
            ->orderBy('firstname')
            ->get()
            ->toArray();

        $classRows = DB::table('student_class as sc')
            ->select('sc.student_id', 'cs.class_section_name')
            ->join('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
            ->when($schoolYear !== '', fn ($q) => $q->where('sc.school_year', $schoolYear))
            ->get()
            ->map(fn ($r) => (array) $r)
            ->all();

        $classMap = [];
        foreach ($classRows as $row) {
            $studentId = (int) ($row['student_id'] ?? 0);
            $name = trim((string) ($row['class_section_name'] ?? ''));
            if ($studentId <= 0 || $name === '') {
                continue;
            }
            $classMap[$studentId][] = $name;
        }

        $attachClasses = static function (array $students) use ($classMap): array {
            foreach ($students as &$student) {
                $studentId = (int) ($student['id'] ?? 0);
                $names = $classMap[$studentId] ?? [];
                $names = array_values(array_unique(array_filter($names)));
                $student['class_sections'] = $names;
                $student['class_section_name'] = !empty($names) ? implode(', ', $names) : 'No class assigned';
            }
            unset($student);
            return $students;
        };

        return [
            'active_students' => $attachClasses($activeStudents),
            'removed_students' => $attachClasses($removedStudents),
            'school_year' => $schoolYear,
        ];
    }
}
