<?php

namespace App\Controllers\View;

class ClassPrepController extends PrintablesBaseController
{
    // Compute per-student sticker counts for entire schoolYear (optionally semester).
    protected function computeStickerCountsAll(\CodeIgniter\Database\BaseConnection $db, string $schoolYear, ?string $semester = null): array
    {
        return $this->computeStickerCounts($schoolYear, null, $semester);
    }

    // Compute per-student sticker counts for one class section.
    protected function computeStickerCountsForClass(\CodeIgniter\Database\BaseConnection $db, string $schoolYear, int $classSectionId, ?string $semester = null): array
    {
        return $this->computeStickerCounts($schoolYear, $classSectionId, $semester);
    }

    protected function computeStickerCounts(
        string $schoolYear,
        ?int $classSectionId,
        ?string $semester
    ): array {
        $specialMap   = ['KG' => 1, '1-A' => 3, '1-B' => 4, '2-A' => 5, '2-B' => 5, '9' => 2];
        $isUpperBlock = static fn(string $g) => (bool) preg_match('/^(3|4|5|6|7|8)(-[AB])?$/', trim($g));
        $isGrade5     = static fn(string $g) => (bool) preg_match('/^5(\-|$)/', trim($g));

        $b = $this->db->table('student_class sc')
            ->select('sc.student_id, s.firstname, s.lastname, s.is_new, cs.class_section_name AS grade_label')
            ->join('students s', 's.id = sc.student_id', 'inner')
            ->join('classSection cs', 'cs.class_section_id = sc.class_section_id', 'inner')
            ->join('classes c', 'c.id = cs.class_id', 'inner')
            ->where('sc.school_year', $schoolYear);

        if (!empty($classSectionId)) {
            $b->where('sc.class_section_id', $classSectionId);
        }

        $rows = $b->get()->getResultArray();

        // Exclude Youth and KG (case-insensitive; also ignore variants like youth-*, KG-*)
        $rows = array_values(array_filter($rows, static function ($r) {
            $g = trim((string) $r['grade_label']);
            return $g !== ''
                && !preg_match('/^youth(?:\b|-)/i', $g)
                && !preg_match('/^kg(?:\b|-)/i', $g);
        }));

        $students = [];
        $total    = 0;

        foreach ($rows as $r) {
            $g     = trim((string) $r['grade_label']);
            $isNew = ((int) $r['is_new']) === 1;

            // Primary-only rules
            if (array_key_exists($g, $specialMap)) {
                $p = $specialMap[$g];
            } elseif ($isUpperBlock($g)) {
                $p = $isNew ? 4 : ($isGrade5($g) ? 3 : 2);
            } else {
                $p = 4;
            }

            $total += $p;

            $students[] = [
                'student_id'    => (int) $r['student_id'],
                'firstname'     => trim($r['firstname']),
                'lastname'      => trim($r['lastname']),
                'grade_label'   => $g,
                'primary_count' => $p,
            ];
        }

        return [
            'students' => $students,
            'totals'   => [
                'stickers' => $total,
                'students' => count($students),
            ],
        ];
    }

    /**
     * Compute sticker counts per student (no file I/O).
     *
     * @param BaseConnection $db
     * @param string         $schoolYear e.g. "2025-2026"
     * @param string|null    $semester   e.g. "Fall" (optional filter)
     * @return array{
     *   students: array<int, array{
     *     student_id:int,
     *     firstname:string,
     *     lastname:string,
     *     grade_label:string,
     *     primary_count:int,
     *     secondary_count:int
     *   }>,
     *   totals: array{primary:int, secondary:int, students:int}
     * }
     */
    private function getStickerCountsPerStudent(string $schoolYear, ?string $semester = null): array
    {
        // --- Sticker rules helpers ----------------------------------------------
        $specialMap = [
            'KG' => 1,
            '1-A' => 3,
            '1-B' => 4,
            '2-A' => 5,
            '2-B' => 5,
            '9'   => 2,
        ];
        $isUpperBlock = static function (string $g): bool {
            // 3-A, 3-B, 4-A, 4-B, 5-A, 5-B, 6, 7, 8 (also allow plain 3/4/5/6/7/8)
            return (bool) preg_match('/^(3|4|5|6|7|8)(-[AB])?$/', trim($g));
        };
        $isGrade5 = static function (string $g): bool {
            // "5" OR "5-A"/"5-B"
            return (bool) preg_match('/^5(\-|$)/', trim($g));
        };

        // --- Pull roster: student_class -> classSection -> classes -> students ---
        $builder = $this->db->table('student_class sc')
            ->select([
                'sc.student_id',
                's.firstname',
                's.lastname',
                's.is_new',
                'cs.class_section_name AS grade_label',
            ])
            ->join('students s', 's.id = sc.student_id')
            ->join('classSection cs', 'cs.class_section_id = sc.class_section_id')
            ->join('classes c', 'c.id = cs.class_id')
            ->where('sc.school_year', $schoolYear);


        $rows = $builder->get()->getResultArray();

        // Filter out Youth (any case; includes youth-*), and empty labels
        $rows = array_values(array_filter($rows, static function ($r) {
            $g = trim((string) $r['grade_label']);
            return $g !== '' && strcasecmp($g, 'youth') !== 0 && strncasecmp($g, 'youth-', 6) !== 0;
        }));

        $out = [];
        $totalPrimary = 0;
        $totalSecondary = 0;

        foreach ($rows as $r) {
            $first = trim((string) $r['firstname']);
            $last  = trim((string) $r['lastname']);
            $grade = trim((string) $r['grade_label']);
            $isNew = ((int) $r['is_new']) === 1;

            $primary = 0;
            $secondary = 0;

            // 1) Special fixed grades
            if (array_key_exists($grade, $specialMap)) {
                $primary = (int) $specialMap[$grade];
                $secondary = 0;
            }
            // 2) Upper block 3..8
            elseif ($isUpperBlock($grade)) {
                if ($isNew) {
                    $primary = 4;
                    $secondary = 0;
                } else {
                    $primary = $isGrade5($grade) ? 3 : 2;
                    $secondary = max(0, 4 - $primary);
                }
            }
            // 3) Fallback for other non-Youth labels (e.g., "1", "2", "10", "11")
            else {
                $primary = 4;
                $secondary = 0;
            }

            $totalPrimary  += $primary;
            $totalSecondary += $secondary;

            $out[] = [
                'student_id'     => (int) $r['student_id'],
                'firstname'      => $first,
                'lastname'       => $last,
                'grade_label'    => $grade,
                'primary_count'  => $primary,
                'secondary_count' => $secondary,
            ];
        }

        return [
            'students' => $out,
            'totals' => [
                'primary'  => $totalPrimary,
                'secondary' => $totalSecondary,
                'students' => count($out),
            ],
        ];
    }

    protected function getStickerCountsPerStudentForClass(
        string $schoolYear,
        int $classSectionId,
        ?string $semester = null
    ): array {
        // Reuse exact helpers/rules from getStickerCountsPerStudent()
        $specialMap = [
            '1-A' => 3,
            '1-B' => 4,
            '2-A' => 5,
            '2-B' => 5,
            '9' => 2,
        ];
        $isUpperBlock = static fn($g) => (bool) preg_match('/^(3|4|5|6|7|8)(-[AB])?$/', trim($g));
        $isGrade5     = static fn($g) => (bool) preg_match('/^5(\-|$)/', trim($g));

        $b = $this->db->table('student_class sc')
            ->select('sc.student_id, s.firstname, s.lastname, s.is_new, cs.class_section_name AS grade_label')
            ->join('students s', 's.id = sc.student_id')
            ->join('classSection cs', 'cs.class_section_id = sc.class_section_id')
            ->join('classes c', 'c.id = cs.class_id')
            ->where('sc.school_year', $schoolYear)
            ->where('sc.class_section_id', $classSectionId);


        $rows = $b->get()->getResultArray();

        $rows = array_values(array_filter($rows, static function ($r) {
            $g = trim((string) $r['grade_label']);
            return $g !== '' && strcasecmp($g, 'youth') !== 0 && strncasecmp($g, 'youth-', 6) !== 0;
        }));

        $out = [];
        $tp = 0;
        $ts = 0;
        foreach ($rows as $r) {
            $g = trim((string) $r['grade_label']);
            $isNew = ((int) $r['is_new']) === 1;
            $p = 0;
            $s = 0;

            if (isset($specialMap[$g])) {
                $p = $specialMap[$g];
            } elseif ($isUpperBlock($g)) {
                if ($isNew) {
                    $p = 4;
                } else {
                    $p = $isGrade5($g) ? 3 : 2;
                    $s = max(0, 4 - $p);
                }
            } else {
                $p = 4;
            }

            $tp += $p;
            $ts += $s;

            $out[] = [
                'student_id'      => (int) $r['student_id'],
                'firstname'       => trim($r['firstname']),
                'lastname'        => trim($r['lastname']),
                'grade_label'     => $g,
                'primary_count'   => $p,
                'secondary_count' => $s,
            ];
        }

        return ['students' => $out, 'totals' => ['primary' => $tp, 'secondary' => $ts, 'students' => count($out)]];
    }

    public function previewStickerCounts()
    {
        // Optional: allow class_id filter; if present, preview only that class
        $classId = (int) ($this->request->getGet('class_id') ?? 0);

        if ($classId > 0) {
            // same join as getStickerCountsPerStudent but add class filter
            $result = $this->getStickerCountsPerStudentForClass($this->schoolYear, $classId, $this->semester);
        } else {
            // whole school year
            $result = $this->getStickerCountsPerStudent($this->schoolYear, $this->semester);
        }

        return $this->response->setJSON([
            'status' => 'ok',
            'data'   => $result
        ]);
    }

    public function studentsByClass(int $classSectionId)
    {
        $rows = $this->studentModel
            ->select('students.id, students.firstname, students.lastname, students.gender, cs.class_section_name AS registration_grade')
            ->join('student_class sc', 'sc.student_id = students.id', 'inner')
            ->join('classSection cs', 'cs.class_section_id = sc.class_section_id', 'inner')
            ->where('sc.school_year', $this->schoolYear)
            ->where('sc.class_section_id', $classSectionId)
            ->groupBy('students.id, students.firstname, students.lastname, students.gender, cs.class_section_name')
            ->orderBy('students.firstname', 'ASC')
            ->orderBy('students.lastname', 'ASC')
            ->findAll(1000);

        return $this->response->setJSON($rows);
    }
}
