<?php

namespace App\Services\Reports\Stickers;

use Illuminate\Support\Facades\DB;

class StickerQueryService
{
    public function __construct(private StickerContextService $context)
    {
    }

    public function resolveSchoolYear(?string $schoolYear): string
    {
        return $this->context->schoolYear($schoolYear);
    }

    public function listClassesWithStudents(string $schoolYear): array
    {
        return DB::table('classSection')
            ->select('classSection.class_section_id', 'classSection.class_section_name')
            ->join('student_class', 'student_class.class_section_id', '=', 'classSection.class_section_id')
            ->where('student_class.school_year', $schoolYear)
            ->groupBy('classSection.class_section_id', 'classSection.class_section_name')
            ->orderBy('classSection.class_section_name', 'ASC')
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();
    }

    public function listStudentsByClass(int $classSectionId, string $schoolYear): array
    {
        return DB::table('student_class as sc')
            ->select('s.id', 's.firstname', 's.lastname', 's.registration_grade', 's.gender')
            ->join('students as s', 's.id', '=', 'sc.student_id')
            ->where('sc.class_section_id', $classSectionId)
            ->where('sc.school_year', $schoolYear)
            ->orderBy('s.lastname', 'asc')
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();
    }

    public function listStudentsForYear(string $schoolYear, int $limit = 500): array
    {
        return DB::table('students')
            ->select('students.id', 'students.firstname', 'students.lastname')
            ->join('student_class', 'student_class.student_id', '=', 'students.id')
            ->where('student_class.school_year', $schoolYear)
            ->groupBy('students.id', 'students.firstname', 'students.lastname')
            ->orderBy('students.firstname', 'ASC')
            ->orderBy('students.lastname', 'ASC')
            ->limit($limit)
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();
    }

    public function listStudentsForPrintAll(string $schoolYear, int $limit = 5000): array
    {
        $rows = DB::table('students')
            ->select(
                'students.id',
                'students.firstname',
                'students.lastname',
                'sc.class_section_id',
                'cs.class_section_name',
                'c.id as class_id'
            )
            ->join('student_class as sc', 'sc.student_id', '=', 'students.id')
            ->join('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
            ->join('classes as c', 'c.id', '=', 'cs.class_id')
            ->where('sc.school_year', $schoolYear)
            ->groupBy(
                'students.id',
                'students.firstname',
                'students.lastname',
                'sc.class_section_id',
                'cs.class_section_name',
                'c.id'
            )
            ->orderBy('c.id', 'ASC')
            ->orderBy('cs.class_section_name', 'ASC')
            ->orderBy('students.firstname', 'ASC')
            ->orderBy('students.lastname', 'ASC')
            ->limit($limit)
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();

        return $this->filterExcludedSections($rows);
    }

    public function findStudent(int $studentId): ?array
    {
        $row = DB::table('students')
            ->select('id', 'firstname', 'lastname')
            ->where('id', $studentId)
            ->first();

        return $row ? (array) $row : null;
    }

    private function filterExcludedSections(array $students): array
    {
        return array_values(array_filter($students, static function (array $student): bool {
            $sectionName = trim((string) ($student['class_section_name'] ?? ''));
            if ($sectionName === '') {
                return false;
            }
            return !preg_match('/^(youth|kg)(?:\b|-)/i', $sectionName);
        }));
    }
}
