<?php
declare(strict_types=1);
namespace BranchAdmin\Controllers;

class BranchExamResultController extends BranchBaseController
{
    public function index(): void
    {
        requireBranchAdmin();
        $branchId = $this->getBranchId();
        $exams = [];
        try {
            $stmt = $this->db->prepare("SELECT e.id, e.title, e.total_marks, e.pass_marks,
                (SELECT COUNT(*) FROM exam_questions q WHERE q.exam_id = e.id) AS question_count,
                (SELECT COUNT(*) FROM exam_results er WHERE er.exam_id = e.id) AS appeared_count,
                (SELECT COUNT(*) FROM exam_results er WHERE er.exam_id = e.id AND er.status = 'pass') AS pass_count,
                (SELECT COUNT(*) FROM exam_results er WHERE er.exam_id = e.id AND er.status = 'fail') AS fail_count
                FROM exams e WHERE e.branch_id = :bid ORDER BY e.created_at DESC");
            $stmt->execute([':bid' => $branchId]);
            $exams = $stmt->fetchAll() ?: [];
        } catch (\Throwable $e) {}

        $this->branchAdminView('exam_results/index', ['title'=>'Exam Results','currentPage'=>'exam_results','exams'=>$exams]);
    }

    public function showExam(?int $examId = null): void
    {
        requireBranchAdmin();
        if (!$examId || $examId <= 0) { flash('error', 'Invalid exam ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $branchId = $this->getBranchId();

        $stmt = $this->db->prepare("SELECT e.*, c.name AS course_name FROM exams e LEFT JOIN courses c ON e.course_id = c.id WHERE e.id = :eid AND e.branch_id = :bid LIMIT 1");
        $stmt->execute([':eid' => $examId, ':bid' => $branchId]);
        $exam = $stmt->fetch() ?: null;
        if (!$exam) { flash('error', 'Exam not found.'); redirect(BASE_PATH.'/branch/exam-results'); }

        $stmt = $this->db->prepare("SELECT er.*, s.enrollment_no, u.name AS student_name, c.name AS course_name
            FROM exam_results er INNER JOIN students s ON er.student_id = s.id INNER JOIN users u ON s.user_id = u.id LEFT JOIN courses c ON s.course_id = c.id
            WHERE er.exam_id = :eid AND s.branch_id = :bid ORDER BY er.total_obtained DESC");
        $stmt->execute([':eid' => $examId, ':bid' => $branchId]);
        $results = $stmt->fetchAll() ?: [];

        foreach ($results as &$r) {
            $pct = (float)($r['percentage'] ?? 0);
            $r['grade'] = $this->calcGrade($pct);
            $r['division'] = $this->calcDivision($pct);
        }
        unset($r);

        $this->branchAdminView('exam_results/show', ['title'=>'Results: '.($exam['title']??''),'currentPage'=>'exam_results','exam'=>$exam,'results'=>$results]);
    }

    public function editScore(?int $examId = null, ?int $resultId = null): void
    {
        requireBranchAdmin();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid result ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $branchId = $this->getBranchId();
        $stmt = $this->db->prepare("SELECT er.*, s.enrollment_no, u.name AS student_name, e.title AS exam_title, e.pass_marks, e.total_marks AS exam_total
            FROM exam_results er INNER JOIN students s ON er.student_id = s.id INNER JOIN users u ON s.user_id = u.id INNER JOIN exams e ON er.exam_id = e.id
            WHERE er.id = :rid AND s.branch_id = :bid LIMIT 1");
        $stmt->execute([':rid' => $resultId, ':bid' => $branchId]);
        $result = $stmt->fetch() ?: null;
        if (!$result) { flash('error', 'Result not found.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $this->branchAdminView('exam_results/edit', ['title'=>'Edit Score: '.($result['student_name']??''),'currentPage'=>'exam_results','result'=>$result,'exam'=>['id'=>$examId]]);
    }

    public function updateScore(?int $examId = null, ?int $resultId = null): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid result ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $branchId = $this->getBranchId();

        $newObtained = (float)($_POST['total_obtained'] ?? 0);
        $adminRemarks = trim($_POST['admin_remarks'] ?? '') ?: null;

        $stmt = $this->db->prepare("SELECT er.id, er.total_marks, e.pass_marks FROM exam_results er INNER JOIN exams e ON er.exam_id = e.id INNER JOIN students s ON er.student_id = s.id WHERE er.id = :rid AND s.branch_id = :bid LIMIT 1");
        $stmt->execute([':rid' => $resultId, ':bid' => $branchId]);
        $result = $stmt->fetch() ?: null;
        if (!$result) { flash('error', 'Result not found.'); redirect(BASE_PATH.'/branch/exam-results'); }

        $totalMarks = (float)$result['total_marks'];
        $passMarks = (float)$result['pass_marks'];
        $pct = $totalMarks > 0 ? round(($newObtained / $totalMarks) * 100, 2) : 0;
        $status = ($newObtained >= $passMarks || $pct >= 33) ? 'pass' : 'fail';

        try {
            $this->db->prepare("UPDATE exam_results SET total_obtained = :obt, percentage = :pct, status = :st, updated_at = NOW() WHERE id = :rid")
                ->execute([':obt' => $newObtained, ':pct' => $pct, ':st' => $status, ':rid' => $resultId]);
            flash('success', "Score updated: {$newObtained}/{$totalMarks} ({$pct}%, {$status})");
        } catch (\Throwable $e) { flash('error', 'Failed: ' . $e->getMessage()); }
        redirect(BASE_PATH . '/branch/exam-results/' . $examId);
    }

    public function approve(?int $resultId = null): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        try {
            $this->db->prepare("UPDATE exam_results SET branch_approved = 1, approved_at = NOW() WHERE id = :rid")->execute([':rid' => $resultId]);
            flash('success', 'Result approved.');
        } catch (\Throwable $e) { flash('error', 'Failed.'); }
        redirect($_SERVER['HTTP_REFERER'] ?? BASE_PATH . '/branch/exam-results');
    }

    public function unapprove(?int $resultId = null): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        try {
            $this->db->prepare("UPDATE exam_results SET branch_approved = 0 WHERE id = :rid")->execute([':rid' => $resultId]);
            flash('success', 'Result unapproved.');
        } catch (\Throwable $e) { flash('error', 'Failed.'); }
        redirect($_SERVER['HTTP_REFERER'] ?? BASE_PATH . '/branch/exam-results');
    }

    public function marksheet(?int $resultId = null): void
    {
        requireBranchAdmin();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $branchId = $this->getBranchId();
        $stmt = $this->db->prepare("SELECT er.*, e.title AS exam_title, s.enrollment_no, u.name AS student_name, b.name AS branch_name, b.branch_code
            FROM exam_results er INNER JOIN exams e ON er.exam_id = e.id INNER JOIN students s ON er.student_id = s.id INNER JOIN users u ON s.user_id = u.id INNER JOIN branches b ON s.branch_id = b.id
            WHERE er.id = :rid AND s.branch_id = :bid LIMIT 1");
        $stmt->execute([':rid' => $resultId, ':bid' => $branchId]);
        $result = $stmt->fetch() ?: null;
        if (!$result) { flash('error', 'Not found.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $result['grade'] = $this->calcGrade((float)$result['percentage']);
        $result['division'] = $this->calcDivision((float)$result['percentage']);
        $this->branchAdminView('exam_results/marksheet', ['title'=>'Marksheet','currentPage'=>'exam_results','result'=>$result]);
    }

    public function certificate(?int $resultId = null): void
    {
        requireBranchAdmin();
        if (!$resultId || $resultId <= 0) { flash('error', 'Invalid ID.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $branchId = $this->getBranchId();
        $stmt = $this->db->prepare("SELECT er.*, e.title AS exam_title, s.enrollment_no, u.name AS student_name, b.name AS branch_name, b.branch_code
            FROM exam_results er INNER JOIN exams e ON er.exam_id = e.id INNER JOIN students s ON er.student_id = s.id INNER JOIN users u ON s.user_id = u.id INNER JOIN branches b ON s.branch_id = b.id
            WHERE er.id = :rid AND s.branch_id = :bid LIMIT 1");
        $stmt->execute([':rid' => $resultId, ':bid' => $branchId]);
        $result = $stmt->fetch() ?: null;
        if (!$result) { flash('error', 'Not found.'); redirect(BASE_PATH.'/branch/exam-results'); }
        $result['grade'] = $this->calcGrade((float)$result['percentage']);
        $result['division'] = $this->calcDivision((float)$result['percentage']);
        $this->branchAdminView('exam_results/certificate', ['title'=>'Certificate','currentPage'=>'exam_results','result'=>$result]);
    }

    private function calcGrade(float $pct): string
    {
        if ($pct >= 90) return 'A+';
        if ($pct >= 80) return 'A';
        if ($pct >= 70) return 'B+';
        if ($pct >= 60) return 'B';
        if ($pct >= 45) return 'C';
        if ($pct >= 33) return 'D';
        return 'F';
    }

    private function calcDivision(float $pct): string
    {
        if ($pct >= 60) return 'First Division';
        if ($pct >= 45) return 'Second Division';
        if ($pct >= 33) return 'Third Division';
        return 'Fail';
    }
}
