<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;

/**
 * Exam Controller
 *
 * Handles exam listing, taking exams, submitting answers,
 * and viewing exam results.
 */
class ExamController extends Controller
{
    /**
     * Display all published exams.
     *
     * @return void
     */
    public function index(): void
    {
        $examModel = $this->model('Exam');

        $exams = $examModel->getPublished();

        $this->view('exam/index', [
            'title'      => 'Online Exams - Gmind Institute',
            'exams'      => $exams,
            'currentNav' => 'exam',
        ]);
    }

    /**
     * Display an exam for a student to take.
     *
     * Requires the student to be logged in. Loads the exam
     * with all its questions for the exam interface.
     *
     * @param int $id The exam ID
     * @return void
     */
    public function take(int $id): void
    {
        requireLogin();

        $examModel = $this->model('Exam');

        $exam = $examModel->getWithQuestions($id);

        if (empty($exam) || !(bool) $exam['is_published']) {
            flash('error', 'Exam not found or not available.');
            redirect('/exam');
        }

        // Check if student already took this exam
        $user = getCurrentUser();
        if ($user !== null) {
            $studentModel = $this->model('Student');
            $student = $studentModel->getByUserId((int) $user['id']);

            if ($student !== null) {
                $existingResult = $examModel->getResult($id, (int) $student['id']);
                if ($existingResult !== null) {
                    flash('info', 'You have already taken this exam.');
                    redirect('/exam/' . $id . '/result');
                }
            }
        }

        // Remove correct answers from questions before sending to view
        $safeQuestions = array_map(function (array $q): array {
            unset($q['correct_answer']);
            return $q;
        }, $exam['questions']);

        $exam['questions'] = $safeQuestions;

        $this->view('exam/take', [
            'title'      => $exam['title'] . ' - Gmind Institute',
            'exam'       => $exam,
            'currentNav' => 'exam',
        ]);
    }

    /**
     * Process exam submission: calculate score and store result.
     *
     * Requires the student to be logged in. Validates CSRF token,
     * calculates the score from submitted answers, and stores
     * the exam result.
     *
     * @param int $id The exam ID
     * @return void
     */
    public function submit(int $id): void
    {
        requireLogin();
        $this->validateCsrf();

        $examModel = $this->model('Exam');
        $exam = $examModel->find($id);

        if (empty($exam) || !(bool) $exam['is_published']) {
            flash('error', 'Exam not found or not available.');
            redirect('/exam');
        }

        // Get current student
        $user = getCurrentUser();
        if ($user === null) {
            flash('error', 'Please log in to submit an exam.');
            redirect('/login');
        }

        $studentModel = $this->model('Student');
        $student = $studentModel->getByUserId((int) $user['id']);

        if ($student === null) {
            flash('error', 'Student record not found. Please contact administration.');
            redirect('/exam');
        }

        $studentId = (int) $student['id'];

        // Check if already submitted
        $existingResult = $examModel->getResult($id, $studentId);
        if ($existingResult !== null) {
            flash('info', 'You have already submitted this exam.');
            redirect('/exam/' . $id . '/result');
        }

        // Collect answers from POST (format: answers[question_id] = 'a'|'b'|'c'|'d')
        $rawAnswers = $_POST['answers'] ?? [];
        $answers = [];

        foreach ($rawAnswers as $questionId => $answer) {
            $qId = (int) $questionId;
            $ans = sanitize((string) $answer);
            if (in_array($ans, ['a', 'b', 'c', 'd'], true)) {
                $answers[$qId] = $ans;
            }
        }

        // Calculate score
        $examResultModel = $this->model('ExamResult');
        $score = $examResultModel->calculateScore($id, $answers);

        try {
            // Store the exam result
            $examResultModel->create([
                'exam_id'        => $id,
                'student_id'     => $studentId,
                'total_obtained' => $score['obtained'],
                'total_marks'    => $score['total'],
                'percentage'     => $score['percentage'],
                'status'         => $score['status'],
                'started_at'     => $_POST['started_at'] ?? date('Y-m-d H:i:s'),
                'completed_at'   => date('Y-m-d H:i:s'),
            ]);

            flash('success', $score['status'] === 'pass'
                ? 'Congratulations! You passed the exam with ' . $score['percentage'] . '%.'
                : 'You scored ' . $score['percentage'] . '%. Keep studying and try again!');
            redirect('/exam/' . $id . '/result');
        } catch (\Throwable $e) {
            error_log('Exam submission error: ' . $e->getMessage());
            flash('error', 'Something went wrong submitting your exam. Please try again.');
            redirect('/exam/' . $id);
        }
    }

    /**
     * Display the exam result for the current student.
     *
     * Requires the student to be logged in.
     *
     * @param int $id The exam ID
     * @return void
     */
    public function result(int $id): void
    {
        requireLogin();

        $user = getCurrentUser();
        if ($user === null) {
            flash('error', 'Please log in to view exam results.');
            redirect('/login');
        }

        $studentModel = $this->model('Student');
        $student = $studentModel->getByUserId((int) $user['id']);

        if ($student === null) {
            flash('error', 'Student record not found.');
            redirect('/exam');
        }

        $examModel = $this->model('Exam');
        $result = $examModel->getResult($id, (int) $student['id']);

        if ($result === null) {
            flash('error', 'No result found for this exam.');
            redirect('/exam');
        }

        $this->view('exam/result', [
            'title'      => 'Exam Result - Gmind Institute',
            'result'     => $result,
            'currentNav' => 'exam',
        ]);
    }
}
