<?php

namespace App\Controllers\View;
use App\Controllers\BaseController;
use CodeIgniter\Controller;
use App\Models\TeacherClassModel;
use App\Models\StudentModel;
use App\Models\ConfigurationModel;
use App\Models\GradingLockModel;
use App\Models\MissingScoreOverrideModel;

class FinalController extends BaseController
{
    protected $db;
    protected $schoolYear;
    protected $semester;
    protected $configModel;
    protected $studentModel;
    protected $teacherClassModel;
    protected $gradingLockModel;
    protected $missingScoreOverrideModel;

    public function __construct()
    {
        $this->db = \Config\Database::connect();
        $this->configModel = new ConfigurationModel();
        $this->studentModel = new StudentModel();
        $this->teacherClassModel = new TeacherClassModel();
        $this->schoolYear = $this->configModel->getConfig('school_year');
        $this->semester = $this->configModel->getConfig('semester');
        $this->gradingLockModel = new GradingLockModel();
        $this->missingScoreOverrideModel = new MissingScoreOverrideModel();
    }

    public function add()
    {
        // Accept class_section_id from POST/GET with session fallback
        $incoming = $this->request->getPost('class_section_id')
            ?? $this->request->getGet('class_section_id')
            ?? session()->get('class_section_id');

        $classSectionId = (int) ($incoming ?: 0);
        if ($classSectionId <= 0) {
            return redirect()->back()->with('status', 'Missing class section.');
        }

        // Persist for downstream calls
        session()->set('class_section_id', $classSectionId);

        $semester = $this->getTeacherSelectedSemester();
        $schoolYear = $this->schoolYear;
        try {
            $result = $this->getSavedScores($classSectionId, $semester, $schoolYear);
            $missingOkMap = $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $schoolYear, 'final_exam');

            return view('teacher/add_final_exam', [
                'students'       => $result['students'],
                'semester'       => $result['semester'],
                'schoolYear'     => $result['schoolYear'],
                'classSectionId' => $classSectionId,
                'missingOkMap'   => $missingOkMap,
            ]);
        } catch (\Throwable $e) {
            return redirect()->back()->with('status', $e->getMessage());
        }
    }

    public function showFinalMngt()
    {
        $incoming = $this->request->getPost('class_section_id')
            ?? $this->request->getGet('class_section_id')
            ?? session()->get('class_section_id');

        $classSectionId = (int) ($incoming ?: 0);
        if ($classSectionId <= 0) {
            return redirect()->back()->with('status', 'Missing class section.');
        }

        $semester = $this->getTeacherSelectedSemester();
        $schoolYear = $this->schoolYear;
        try {
            $result = $this->getSavedScores($classSectionId, $semester, $schoolYear);
            $scoresLocked = $this->gradingLockModel->isLocked($classSectionId, $semester, $schoolYear);

            return view('grading/final', [
                'students'       => $result['students'],
                'semester'       => $result['semester'],
                'schoolYear'     => $result['schoolYear'],
                'classSectionId' => $classSectionId,
                'scoresLocked'   => $scoresLocked,
            ]);
        } catch (\Throwable $e) {
            return redirect()->back()->with('status', $e->getMessage());
        }
    }

    private function getSavedScores(int $classSectionId, string $semester, string $schoolYear): array
    {
        if ($classSectionId <= 0) {
            throw new \InvalidArgumentException('Invalid class section id.');
        }

        session()->set('class_section_id', $classSectionId);

        // Subquery: pick ONE final exam row per student (latest by id)
        $latestFinalSub = $this->db->table('final_exam')
            ->select('student_id, MAX(id) AS max_id')
            ->where('class_section_id', $classSectionId)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->groupBy('student_id')
            ->getCompiledSelect();

        // Main query: roster + LEFT JOIN the single final exam row
        $qb = $this->studentModel
            ->select('
            s.id AS student_id,
            s.school_id,
            s.firstname,
            s.lastname,
            fe.score
        ')
            ->from('students s')
            ->join(
                'student_class sc',
                'sc.student_id = s.id
             AND sc.class_section_id = ' . (int) $classSectionId . '
             AND sc.school_year = ' . $this->db->escape($schoolYear),
                'inner',
                false
            )
            ->join('(' . $latestFinalSub . ') fl', 'fl.student_id = s.id', 'left', false)
            ->join('final_exam fe', 'fe.id = fl.max_id', 'left')
            ->orderBy('s.lastname', 'ASC')
            ->orderBy('s.firstname', 'ASC');

        $qb->distinct();
        $rows = $qb->get()->getResultArray();

        // Ensure one row per student
        $unique = [];
        foreach ($rows as $r) {
            $unique[(int)$r['student_id']] = $r;
        }
        $students = array_values($unique);

        return [
            'students'   => $students,
            'semester'   => $semester,
            'schoolYear' => $schoolYear,
        ];
    }

    private function getTeacherSelectedSemester(): string
    {
        helper('semester_selection_helper');
        return selected_teacher_semester();
    }
}
