<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Services\AssessmentService;
use App\Services\CourseService;
use App\Services\EnrollmentService;

class AssessmentController extends Controller
{
    private AssessmentService $assessments;
    private CourseService $courses;
    private EnrollmentService $enrollments;

    public function __construct()
    {
        $this->assessments = new AssessmentService();
        $this->courses = new CourseService();
        $this->enrollments = new EnrollmentService();
    }

    public function manage(Request $request): string
    {
        $this->requireCreator();
        $course = $this->managedCourse($request);

        return $this->view('assessments/manage', [
            'title' => 'Teste final',
            'course' => $course,
            'questions' => $this->assessments->questionsForCourse((int) $course['id']),
        ]);
    }

    public function storeQuestion(Request $request): void
    {
        $this->requireCreator();
        $this->guardCsrf($request);
        $course = $this->managedCourse($request);

        $result = $this->assessments->addQuestion((int) $course['id'], $request->all(), current_user());

        flash($result['ok'] ? 'success' : 'error', $result['ok'] ? 'Pergunta adicionada.' : $result['error']);
        app()->response()->redirect('/manage/courses/assessment?id=' . $course['id']);
    }

    public function deleteQuestion(Request $request): void
    {
        $this->requireCreator();
        $this->guardCsrf($request);
        $course = $this->managedCourse($request);

        $result = $this->assessments->deleteQuestion((int) $course['id'], (int) $request->post('question_id'), current_user());

        flash($result['ok'] ? 'success' : 'error', $result['ok'] ? 'Pergunta removida.' : $result['error']);
        app()->response()->redirect('/manage/courses/assessment?id=' . $course['id']);
    }

    public function take(Request $request): string
    {
        require_role('student');
        $courseId = (int) $request->input('course_id');
        $course = $this->courses->find($courseId);
        $enrollment = $this->enrollments->findEnrollment((int) current_user()['id'], $courseId);

        if (!$course || !$enrollment) {
            flash('error', 'Nao tem acesso a este teste.');
            app()->response()->redirect('/student/courses');
        }

        return $this->view('assessments/take', [
            'title' => 'Teste final',
            'course' => $course,
            'enrollment' => $enrollment,
            'questions' => $this->assessments->questionsForCourse($courseId),
            'bestAttempt' => $this->assessments->bestAttempt((int) $enrollment['id']),
        ]);
    }

    public function submit(Request $request): void
    {
        require_role('student');
        $this->guardCsrf($request);

        $answers = $request->post('answers', []);
        $result = $this->assessments->submitAttempt(
            (int) $request->post('course_id'),
            (int) $request->post('enrollment_id'),
            current_user(),
            is_array($answers) ? $answers : []
        );

        if (!$result['ok']) {
            flash('error', $result['error']);
            app()->response()->back();
        }

        $attempt = $result['attempt'];
        flash($attempt['passed'] ? 'success' : 'error', $attempt['passed'] ? 'Teste aprovado com ' . $attempt['score'] . '%.' : 'Teste submetido com ' . $attempt['score'] . '%. Tente novamente.');
        app()->response()->redirect('/learn/quiz?course_id=' . $request->post('course_id'));
    }

    private function managedCourse(Request $request): array
    {
        $course = $this->courses->find((int) $request->input('id', $request->post('course_id')));

        if (!$course || !$this->courses->canManage($course, current_user())) {
            flash('error', 'Curso nao encontrado.');
            app()->response()->redirect('/manage/courses');
        }

        return $course;
    }

    private function requireCreator(): void
    {
        require_auth();

        if (!in_array(current_user()['role'] ?? '', ['admin', 'instructor', 'institution'], true)) {
            flash('error', 'Apenas instrutores, instituicoes e admin podem gerir testes.');
            app()->response()->redirect('/dashboard');
        }
    }

    private function guardCsrf(Request $request): void
    {
        if (!verify_csrf((string) $request->post('_csrf_token', ''))) {
            flash('error', 'Sessao expirada. Tente novamente.');
            app()->response()->back();
        }
    }
}
