<?php

namespace App\Http\Controllers;

use App\Http\Traits\ResponseTrait;
use App\Models\ExamAttempt;
use App\Models\ExamAnswer;
use App\Models\ExamQuestion;
use App\Models\Certificate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class ExamAttemptController extends Controller
{
    use ResponseTrait;

    /**
     * Get exam attempt details (for resuming)
     * GET /exam-attempts/{id}
     */
    public function show(Request $request, ExamAttempt $examAttempt)
    {
        $user = $request->user();

        // Verify ownership
        if ($examAttempt->user_id !== $user->id) {
            return $this->notFoundResponse();
        }

        // Check if expired
        if ($examAttempt->isExpired() && $examAttempt->status === 'in_progress') {
            $examAttempt->update(['status' => 'expired']);
        }

        $exam = $examAttempt->exam;
        $questions = $exam->questions()->orderBy('order')->get()->map(function ($question) use ($examAttempt) {
            $answer = ExamAnswer::where('attempt_id', $examAttempt->id)
                ->where('question_id', $question->id)
                ->first();

            return [
                'id' => $question->id,
                'question' => $question->question,
                'type' => $question->type,
                'options' => $question->options,
                'points' => $question->points,
                'answer' => $answer ? $answer->answer : null,
            ];
        });

        $answers = ExamAnswer::where('attempt_id', $examAttempt->id)
            ->pluck('answer', 'question_id')
            ->toArray();

        $data = [
            'id' => $examAttempt->id,
            'exam_id' => $examAttempt->exam_id,
            'status' => $examAttempt->status,
            'started_at' => $examAttempt->started_at,
            'submitted_at' => $examAttempt->submitted_at,
            'expires_at' => $examAttempt->expires_at,
            'time_remaining_seconds' => $examAttempt->time_remaining_seconds,
            'answers' => $answers,
            'questions' => $questions,
        ];

        return $this->successResponse($data, 'Exam attempt retrieved successfully');
    }

    /**
     * Save exam answers (auto-save)
     * PUT /exam-attempts/{id}/answers
     */
    public function updateAnswers(Request $request, ExamAttempt $examAttempt)
    {
        $user = $request->user();

        // Verify ownership
        if ($examAttempt->user_id !== $user->id) {
            return $this->notFoundResponse();
        }

        // Check if attempt is still in progress
        if ($examAttempt->status !== 'in_progress') {
            return $this->errorResponse('Cannot update answers for a submitted or expired attempt');
        }

        if ($examAttempt->isExpired()) {
            $examAttempt->update(['status' => 'expired']);
            return $this->errorResponse('Exam attempt has expired');
        }

        $request->validate([
            'answers' => 'required|array',
            'answers.*' => 'nullable|string',
        ]);

        DB::transaction(function () use ($examAttempt, $request) {
            foreach ($request->answers as $questionId => $answer) {
                ExamAnswer::updateOrCreate(
                    [
                        'attempt_id' => $examAttempt->id,
                        'question_id' => $questionId,
                    ],
                    [
                        'answer' => $answer,
                        'answered_at' => now(),
                    ]
                );
            }

            // Update questions answered count
            $questionsAnswered = ExamAnswer::where('attempt_id', $examAttempt->id)
                ->whereNotNull('answer')
                ->count();
            
            $examAttempt->update(['questions_answered' => $questionsAnswered]);
        });

        return $this->successResponse([
            'saved_at' => now(),
        ], 'Answers saved successfully');
    }

    /**
     * Submit exam for grading
     * POST /exam-attempts/{id}/submit
     */
    public function submit(Request $request, ExamAttempt $examAttempt)
    {
        $user = $request->user();

        // Verify ownership
        if ($examAttempt->user_id !== $user->id) {
            return $this->notFoundResponse();
        }

        // Check if already submitted
        if ($examAttempt->status === 'submitted') {
            return $this->errorResponse('Exam has already been submitted');
        }

        if ($examAttempt->isExpired() && $examAttempt->status === 'in_progress') {
            $examAttempt->update(['status' => 'expired']);
            return $this->errorResponse('Exam attempt has expired');
        }

        $request->validate([
            'answers' => 'required|array',
            'answers.*' => 'nullable|string',
        ]);

        $result = DB::transaction(function () use ($examAttempt, $request) {
            $exam = $examAttempt->exam;
            $totalPoints = 0;
            $earnedPoints = 0;
            $correctAnswers = 0;
            $incorrectAnswers = 0;

            // Save/update all answers
            foreach ($request->answers as $questionId => $answer) {
                $question = ExamQuestion::find($questionId);
                if (!$question || $question->exam_id !== $exam->id) {
                    continue;
                }

                $totalPoints += $question->points;
                $isCorrect = false;
                $pointsAwarded = 0;

                // Grade the answer
                if ($question->type === 'multiple_choice' || $question->type === 'single_choice' || $question->type === 'true_false') {
                    if ($answer === $question->correct_answer) {
                        $isCorrect = true;
                        $pointsAwarded = $question->points;
                        $correctAnswers++;
                    } else {
                        $incorrectAnswers++;
                    }
                } elseif ($question->type === 'essay' || $question->type === 'short_answer') {
                    // Manual grading - mark as null for now
                    $isCorrect = null;
                    $pointsAwarded = 0;
                }

                ExamAnswer::updateOrCreate(
                    [
                        'attempt_id' => $examAttempt->id,
                        'question_id' => $questionId,
                    ],
                    [
                        'answer' => $answer,
                        'is_correct' => $isCorrect,
                        'points_awarded' => $pointsAwarded,
                        'answered_at' => now(),
                    ]
                );

                $earnedPoints += $pointsAwarded;
            }

            // Calculate score percentage
            $score = $totalPoints > 0 ? round(($earnedPoints / $totalPoints) * 100) : 0;
            $passed = $score >= $exam->passing_score;

            // Calculate time taken
            $timeTaken = now()->diffInSeconds($examAttempt->started_at);

            // Update attempt
            $examAttempt->update([
                'status' => 'submitted',
                'submitted_at' => now(),
                'score' => $score,
                'passed' => $passed,
                'questions_answered' => count($request->answers),
                'correct_answers' => $correctAnswers,
                'incorrect_answers' => $incorrectAnswers,
                'time_taken_seconds' => $timeTaken,
            ]);

            // Generate certificate if passed
            $certificate = null;
            if ($passed) {
                $certificate = Certificate::create([
                    'user_id' => $examAttempt->user_id,
                    'exam_id' => $exam->id,
                    'attempt_id' => $examAttempt->id,
                    'title' => $exam->title . ' Certificate',
                    'issuer' => 'ARMPO',
                    'issued_date' => now(),
                    'score' => $score,
                    'verified' => true,
                ]);
            }

            return [
                'attempt_id' => $examAttempt->id,
                'score' => $score,
                'passing_score' => $exam->passing_score,
                'passed' => $passed,
                'questions_answered' => count($request->answers),
                'total_questions' => $exam->questions()->count(),
                'correct_answers' => $correctAnswers,
                'incorrect_answers' => $incorrectAnswers,
                'time_taken_seconds' => $timeTaken,
                'attempt_number' => $examAttempt->attempt_number,
                'max_attempts' => $exam->max_attempts,
                'attempts_remaining' => max(0, $exam->max_attempts - $examAttempt->attempt_number),
                'certificate_eligible' => $passed,
                'certificate_id' => $certificate ? $certificate->id : null,
            ];
        });

        return $this->successResponse([
            'result' => $result,
        ], 'Exam submitted successfully');
    }

    /**
     * Get user's exam attempts
     * GET /exam-attempts
     */
    public function index(Request $request)
    {
        $user = $request->user();
        $query = ExamAttempt::where('user_id', $user->id)
            ->with('exam:id,title');

        // Filter by exam_id
        if ($request->has('exam_id')) {
            $query->where('exam_id', $request->exam_id);
        }

        // Filter by status
        if ($request->has('status')) {
            $query->where('status', $request->status);
        }

        $perPage = $request->per_page ?? 15;
        $attempts = $query->orderBy('created_at', 'desc')->paginate($perPage);

        $attempts->getCollection()->transform(function ($attempt) {
            return [
                'id' => $attempt->id,
                'exam' => [
                    'id' => $attempt->exam->id,
                    'title' => $attempt->exam->title,
                ],
                'status' => $attempt->status,
                'score' => $attempt->score,
                'passed' => $attempt->passed,
                'started_at' => $attempt->started_at,
                'submitted_at' => $attempt->submitted_at,
            ];
        });

        return $this->paginatedResponse($attempts, 'Exam attempts retrieved successfully');
    }
}
