<?php

namespace App\Http\Controllers;

use App\Http\Traits\ResponseTrait;
use App\Models\Exam;
use App\Models\ExamAttempt;
use App\Models\ExamBooking;
use App\Models\ExamStudyMaterial;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ExamController extends Controller
{
    use ResponseTrait;

    /**
     * Get available exams
     * GET /exams
     */
    public function index(Request $request)
    {
        $user = $request->user();
        $query = Exam::query();

        // Filter by status
        if ($request->has('status')) {
            $status = $request->status;
            if ($status === 'available') {
                $query->available();
            } elseif ($status === 'completed') {
                $examIds = ExamAttempt::where('user_id', $user->id)
                    ->where('status', 'submitted')
                    ->pluck('exam_id')
                    ->unique();
                $query->whereIn('id', $examIds);
            } elseif ($status === 'upcoming') {
                $query->where('available_from', '>', now());
            }
        }

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

        $perPage = $request->per_page ?? 15;
        $exams = $query->paginate($perPage);

        // Add user-specific data
        $exams->getCollection()->transform(function ($exam) use ($user) {
            $attempts = ExamAttempt::where('exam_id', $exam->id)
                ->where('user_id', $user->id)
                ->get();
            
            $attemptsUsed = $attempts->count();
            $passed = $attempts->where('passed', true)->isNotEmpty();
            
            return [
                'id' => $exam->id,
                'title' => $exam->title,
                'description' => $exam->description,
                'duration_minutes' => $exam->duration_minutes,
                'passing_score' => $exam->passing_score,
                'max_attempts' => $exam->max_attempts,
                'attempts_used' => $attemptsUsed,
                'questions_count' => $exam->questions()->count(),
                'category' => $exam->category,
                'available_from' => $exam->available_from,
                'available_until' => $exam->available_until,
                'status' => $this->getExamStatus($exam),
                'passed' => $passed ? true : null,
            ];
        });

        return $this->paginatedResponse($exams, 'Exams retrieved successfully');
    }

    /**
     * Get exam details
     * GET /exams/{id}
     */
    public function show(Request $request, Exam $exam)
    {
        $user = $request->user();
        
        $attempts = ExamAttempt::where('exam_id', $exam->id)
            ->where('user_id', $user->id)
            ->get();
        
        $attemptsUsed = $attempts->count();
        $canTake = $exam->canTake($user->id);

        $data = [
            'id' => $exam->id,
            'title' => $exam->title,
            'description' => $exam->description,
            'duration_minutes' => $exam->duration_minutes,
            'passing_score' => $exam->passing_score,
            'max_attempts' => $exam->max_attempts,
            'attempts_used' => $attemptsUsed,
            'questions_count' => $exam->questions()->count(),
            'instructions' => $exam->instructions,
            'available_from' => $exam->available_from,
            'available_until' => $exam->available_until,
            'can_take' => $canTake['can_take'],
            'attempts_remaining' => $canTake['attempts_remaining'],
        ];

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

    /**
     * Start exam attempt
     * POST /exams/{id}/start
     */
    public function start(Request $request, Exam $exam)
    {
        $user = $request->user();

        // Check if user can take exam
        $canTake = $exam->canTake($user->id);
        if (!$canTake['can_take']) {
            return $this->errorResponse('You cannot take this exam. Attempts remaining: ' . $canTake['attempts_remaining']);
        }

        // Check if there's an in-progress attempt
        $inProgressAttempt = ExamAttempt::where('exam_id', $exam->id)
            ->where('user_id', $user->id)
            ->where('status', 'in_progress')
            ->where('expires_at', '>', now())
            ->first();

        if ($inProgressAttempt) {
            return $this->successResponse([
                'attempt' => $this->formatAttempt($inProgressAttempt, $exam),
            ], 'Resuming existing exam attempt');
        }

        // Create new attempt
        $attemptNumber = ExamAttempt::where('exam_id', $exam->id)
            ->where('user_id', $user->id)
            ->count() + 1;

        $startedAt = now();
        $expiresAt = $startedAt->copy()->addMinutes($exam->duration_minutes);

        $attempt = ExamAttempt::create([
            'exam_id' => $exam->id,
            'user_id' => $user->id,
            'status' => 'in_progress',
            'started_at' => $startedAt,
            'expires_at' => $expiresAt,
            'attempt_number' => $attemptNumber,
        ]);

        // Get questions (randomized)
        $questions = $exam->questions()->inRandomOrder()->get()->map(function ($question) {
            return [
                'id' => $question->id,
                'question' => $question->question,
                'type' => $question->type,
                'options' => $question->options,
                'points' => $question->points,
            ];
        });

        $response = [
            'code' => 201,
            'error' => false,
            'status' => 'success',
            'message' => 'Exam attempt started successfully',
            'data' => [
                'attempt' => [
                    'id' => $attempt->id,
                    'exam_id' => $attempt->exam_id,
                    'started_at' => $attempt->started_at,
                    'expires_at' => $attempt->expires_at,
                    'time_remaining_seconds' => $attempt->time_remaining_seconds,
                    'questions' => $questions,
                ],
            ],
        ];
        return response()->json($response, 201, [], JSON_NUMERIC_CHECK);
    }

    /**
     * Book exam slot
     * POST /exams/{id}/book
     */
    public function book(Request $request, Exam $exam)
    {
        $request->validate([
            'exam_type' => 'required|string|in:online,in_person,hybrid',
            'date' => 'required|date|after_or_equal:today',
            'time' => 'required|date_format:H:i',
            'location' => 'nullable|string|max:255',
        ]);

        $user = $request->user();

        $booking = ExamBooking::create([
            'exam_id' => $exam->id,
            'user_id' => $user->id,
            'exam_type' => $request->exam_type,
            'date' => $request->date,
            'time' => $request->time,
            'location' => $request->location,
            'status' => 'pending',
        ]);

        $response = [
            'code' => 201,
            'error' => false,
            'status' => 'success',
            'message' => 'Exam slot booked successfully',
            'data' => [
                'booking' => [
                    'id' => $booking->id,
                    'exam_id' => $booking->exam_id,
                    'date' => $booking->date,
                    'time' => $booking->time,
                    'location' => $booking->location,
                    'status' => $booking->status,
                ],
            ],
        ];
        return response()->json($response, 201, [], JSON_NUMERIC_CHECK);
    }

    /**
     * Get study materials for exam
     * GET /exams/{id}/study-materials
     */
    public function studyMaterials(Request $request, Exam $exam)
    {
        $materials = $exam->studyMaterials()->get()->map(function ($material) {
            return [
                'id' => $material->id,
                'title' => $material->title,
                'type' => $material->type,
                'file_url' => $material->file_url,
                'size' => $material->size,
                'download_count' => $material->download_count,
            ];
        });

        return $this->successResponse($materials, 'Study materials retrieved successfully');
    }

    /**
     * Get exam status for user
     */
    private function getExamStatus(Exam $exam): string
    {
        if (!$exam->is_active) {
            return 'inactive';
        }

        if ($exam->available_from && $exam->available_from > now()) {
            return 'upcoming';
        }

        if ($exam->available_until && $exam->available_until < now()) {
            return 'expired';
        }

        return 'available';
    }

    /**
     * Format attempt data
     */
    private function formatAttempt(ExamAttempt $attempt, Exam $exam): array
    {
        $questions = $exam->questions()->inRandomOrder()->get()->map(function ($question) use ($attempt) {
            $answer = $question->answerForAttempt($attempt->id);
            return [
                'id' => $question->id,
                'question' => $question->question,
                'type' => $question->type,
                'options' => $question->options,
                'points' => $question->points,
                'answer' => $answer ? $answer->answer : null,
            ];
        });

        return [
            'id' => $attempt->id,
            'exam_id' => $attempt->exam_id,
            'started_at' => $attempt->started_at,
            'expires_at' => $attempt->expires_at,
            'time_remaining_seconds' => $attempt->time_remaining_seconds,
            'questions' => $questions,
        ];
    }
}
