<?php

namespace App\Http\Controllers\Student;

use App\Http\Controllers\Controller;
use App\Models\Quiz;
use App\Models\QuizAttempt;
use App\Models\QuizQuestion;
use App\Models\QuizAnswer;
use App\Models\QuizAttemptAnswer;
use App\Models\QuestionBookmark;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class QuizController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware(['auth', 'role:student']);
    }

    /**
     * Display a listing of available quizzes.
     *
     * @return \Illuminate\View\View
     */
    public function index(Request $request)
    {
        try {
            // Query quizzes - show active ones, or all if none are active (for debugging)
            $query = Quiz::with(['course', 'book', 'creator']);
            
            // Check if any active quizzes exist
            $hasActiveQuizzes = Quiz::where('is_active', true)->exists();
            
            // If active quizzes exist, only show active ones. Otherwise, show all (for debugging)
            if ($hasActiveQuizzes) {
                $query->where('is_active', true);
            }
            // If no active quizzes, show all quizzes (helps identify if is_active wasn't set)

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

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

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

            $quizzes = $query->orderBy('level')->orderBy('title')->get();

            // Get user's best scores for each quiz
            $userBestScores = [];
            foreach ($quizzes as $quiz) {
                $userBestScores[$quiz->id] = $quiz->getUserBestScore(Auth::id());
            }

            $courses = \App\Models\Course::where('is_active', true)->orderBy('name')->get();
            $books = \App\Models\Book::where('is_active', true)->orderBy('title')->get();

            // Debug logging only in non-production environments
            if (config('app.debug') && app()->environment(['local', 'testing'])) {
                \Log::debug('Quiz Index Query', [
                    'total_quizzes' => $quizzes->count(),
                    'has_active_quizzes' => $hasActiveQuizzes,
                    'total_in_db' => Quiz::count(),
                    'active_in_db' => Quiz::where('is_active', true)->count(),
                    'filters' => $request->only(['level', 'course_id', 'book_id'])
                ]);
            }

            return view('student.quizzes.index', compact('quizzes', 'userBestScores', 'courses', 'books'));
        } catch (\Exception $e) {
            \Log::error('Quiz Index Error', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            // Return empty result instead of crashing
            return view('student.quizzes.index', [
                'quizzes' => collect([]),
                'userBestScores' => [],
                'courses' => collect([]),
                'books' => collect([])
            ]);
        }
    }

    /**
     * Show the quiz and start an attempt.
     *
     * @param  Quiz  $quiz
     * @return \Illuminate\View\View
     */
    public function show(Quiz $quiz, Request $request)
    {
        if (!$quiz->is_active) {
            abort(404);
        }

        $quiz->load(['questions.answers']);

        // Determine mode (study or regular)
        $mode = $request->has('study_mode') ? 'study' : 'regular';

        // Check for existing incomplete attempt (same mode)
        $existingAttempt = QuizAttempt::where('quiz_id', $quiz->id)
            ->where('user_id', Auth::id())
            ->where('mode', $mode)
            ->whereNull('completed_at')
            ->with('attemptAnswers')
            ->first();

        // If starting over, delete existing attempt
        if ($request->has('start_over') && $existingAttempt) {
            $existingAttempt->attemptAnswers()->delete();
            $existingAttempt->delete();
            $existingAttempt = null;
        }

        // Create new attempt or use existing
        if (!$existingAttempt) {
            // Shuffle questions and answers for each user
            $questions = $quiz->questions->shuffle();
            $questionOrder = $questions->pluck('id')->toArray();
            
            foreach ($questions as $question) {
                $question->answers = $question->answers->shuffle();
            }

            $attempt = QuizAttempt::create([
                'quiz_id' => $quiz->id,
                'user_id' => Auth::id(),
                'mode' => $mode,
                'started_at' => now(),
                'total_questions' => $quiz->questions->count(),
                'question_order' => $questionOrder,
            ]);
        } else {
            // Restore question order from attempt
            $questionOrder = $existingAttempt->question_order ?? [];
            $questions = $quiz->questions->sortBy(function($question) use ($questionOrder) {
                $index = array_search($question->id, $questionOrder);
                return $index !== false ? $index : 999;
            })->values();
            
            // Shuffle answers for each question
            foreach ($questions as $question) {
                $question->answers = $question->answers->shuffle();
            }

            $attempt = $existingAttempt;
            
            // Ensure started_at is set if it's null (for older attempts)
            if (!$attempt->started_at) {
                $attempt->started_at = $attempt->created_at ?? now();
                $attempt->save();
            }
        }

        // Load attempt answers for progress restoration
        $attempt->load('attemptAnswers');
        
        // Get answered question IDs
        $answeredQuestionIds = $attempt->getAnsweredQuestionIds();
        
        // Get bookmarked question IDs for this user
        $bookmarkedQuestionIds = QuestionBookmark::where('user_id', Auth::id())
            ->whereIn('question_id', $questions->pluck('id'))
            ->pluck('question_id')
            ->toArray();

        return view('student.quizzes.show', compact('quiz', 'attempt', 'questions', 'answeredQuestionIds', 'mode', 'bookmarkedQuestionIds'));
    }

    /**
     * Submit an answer for a question.
     *
     * @param  Request  $request
     * @param  Quiz  $quiz
     * @return \Illuminate\Http\JsonResponse
     */
    public function submitAnswer(Request $request, Quiz $quiz)
    {
        try {
            $validated = $request->validate([
                'question_id' => 'required|integer|exists:quiz_questions,id',
                'answer_id' => 'required|integer|exists:quiz_answers,id',
                'attempt_id' => 'nullable|integer|exists:quiz_attempts,id',
            ]);

            $question = QuizQuestion::findOrFail($validated['question_id']);
            $answer = QuizAnswer::findOrFail($validated['answer_id']);

            // Verify question belongs to quiz
            if ($question->quiz_id !== $quiz->id) {
                return response()->json(['error' => 'Invalid question'], 400);
            }

            // Get attempt - use attempt_id if provided, otherwise find by quiz and user
            if (!empty($validated['attempt_id'])) {
                $attempt = QuizAttempt::where('id', $validated['attempt_id'])
                    ->where('user_id', Auth::id())
                    ->where('quiz_id', $quiz->id)
                    ->whereNull('completed_at')
                    ->first();
                
                if (!$attempt) {
                    return response()->json(['error' => 'Attempt not found or already completed'], 400);
                }
            } else {
                // Find any incomplete attempt for this quiz (regular or study mode)
                $attempt = QuizAttempt::where('quiz_id', $quiz->id)
                    ->where('user_id', Auth::id())
                    ->whereNull('completed_at')
                    ->orderBy('created_at', 'desc')
                    ->first();

                if (!$attempt) {
                    // Default to regular mode if no attempt found
                    $attempt = QuizAttempt::create([
                        'quiz_id' => $quiz->id,
                        'user_id' => Auth::id(),
                        'mode' => 'regular',
                        'started_at' => now(),
                        'total_questions' => $quiz->questions()->count(),
                    ]);
                }
            }

            // Check if answer is correct
            $isCorrect = (bool) $answer->is_correct;

            // Save or update attempt answer
            QuizAttemptAnswer::updateOrCreate(
                [
                    'attempt_id' => $attempt->id,
                    'question_id' => $question->id,
                ],
                [
                    'answer_id' => $answer->id,
                    'is_correct' => $isCorrect,
                ]
            );

            // Get correct answer for feedback
            $correctAnswer = $question->getCorrectAnswer();

            return response()->json([
                'success' => true,
                'is_correct' => $isCorrect,
                'correct_answer' => $correctAnswer ? [
                    'id' => $correctAnswer->id,
                    'text' => $correctAnswer->answer_text,
                ] : null,
                'explanation' => $question->explanation,
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'error' => 'Validation failed',
                'messages' => $e->errors()
            ], 422);
        } catch (\Exception $e) {
            \Log::error('Quiz submit answer error: ' . $e->getMessage(), [
                'quiz_id' => $quiz->id,
                'user_id' => Auth::id(),
                'request' => $request->all(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'error' => 'An error occurred while submitting your answer. Please try again.'
            ], 500);
        }
    }

    /**
     * Complete the quiz attempt.
     *
     * @param  Request  $request
     * @param  Quiz  $quiz
     * @return \Illuminate\Http\RedirectResponse
     */
    public function complete(Request $request, Quiz $quiz)
    {
        try {
            $mode = $request->input('mode', 'regular');
            $attemptId = $request->input('attempt_id');
            
            // If attempt_id is provided, use it directly
            if ($attemptId) {
                $attempt = QuizAttempt::where('id', $attemptId)
                    ->where('user_id', Auth::id())
                    ->where('quiz_id', $quiz->id)
                    ->whereNull('completed_at')
                    ->first();
                
                if (!$attempt) {
                    return redirect()->route('student.quizzes.show', $quiz->id)
                        ->with('error', 'Attempt not found or already completed.');
                }
            } else {
                // Otherwise, find by quiz, user, and mode
                $attempt = QuizAttempt::where('quiz_id', $quiz->id)
                    ->where('user_id', Auth::id())
                    ->where('mode', $mode)
                    ->whereNull('completed_at')
                    ->orderBy('created_at', 'desc')
                    ->first();
                
                if (!$attempt) {
                    return redirect()->route('student.quizzes.show', $quiz->id)
                        ->with('error', 'No incomplete attempt found.');
                }
            }

            // Calculate score
            $correctAnswers = $attempt->attemptAnswers()->where('is_correct', true)->count();
            $totalQuestions = $attempt->total_questions ?: $quiz->questions()->count();
            
            // If total_questions is 0, update it
            if ($attempt->total_questions == 0) {
                $attempt->total_questions = $totalQuestions;
            }
            
            $percentage = $totalQuestions > 0 ? ($correctAnswers / $totalQuestions) * 100 : 0;

            $attempt->update([
                'correct_answers' => $correctAnswers,
                'score' => $correctAnswers,
                'percentage' => round($percentage, 2),
                'completed_at' => now(),
                'total_questions' => $totalQuestions,
            ]);

            // For study mode, don't redirect to result page, just show completion message
            if ($attempt->mode === 'study') {
                return redirect()->route('student.quizzes.show', ['quiz' => $quiz->id, 'study_mode' => 1])
                    ->with('success', 'Study session completed! Your progress has been saved.');
            }

            return redirect()->route('student.quizzes.result', ['quiz' => $quiz->id, 'attempt' => $attempt->id])
                ->with('success', 'Quiz completed!');
        } catch (\Exception $e) {
            \Log::error('Quiz complete error: ' . $e->getMessage(), [
                'quiz_id' => $quiz->id,
                'user_id' => Auth::id(),
                'request' => $request->all(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return redirect()->route('student.quizzes.show', $quiz->id)
                ->with('error', 'An error occurred while completing the quiz. Please try again.');
        }
    }

    /**
     * Show quiz result.
     *
     * @param  Quiz  $quiz
     * @param  QuizAttempt  $attempt
     * @return \Illuminate\View\View
     */
    public function result(Quiz $quiz, QuizAttempt $attempt)
    {
        // Verify attempt belongs to user and quiz
        if ($attempt->user_id !== Auth::id() || $attempt->quiz_id !== $quiz->id) {
            abort(403);
        }

        $quiz->load(['questions.answers']);
        $attempt->load(['attemptAnswers.answer', 'attemptAnswers.question']);

        // Map attempt answers by question ID for easy lookup
        $attemptAnswersMap = [];
        foreach ($attempt->attemptAnswers as $attemptAnswer) {
            $attemptAnswersMap[$attemptAnswer->question_id] = $attemptAnswer;
        }

        return view('student.quizzes.result', compact('quiz', 'attempt', 'attemptAnswersMap'));
    }

    /**
     * Show user's quiz history.
     *
     * @return \Illuminate\View\View
     */
    public function history()
    {
        $attempts = QuizAttempt::where('user_id', Auth::id())
            ->whereNotNull('completed_at')
            ->with(['quiz.course', 'quiz.book'])
            ->orderBy('completed_at', 'desc')
            ->paginate(20);

        return view('student.quizzes.history', compact('attempts'));
    }

    /**
     * Show all incorrect answers for review.
     *
     * @param  Request  $request
     * @return \Illuminate\View\View
     */
    public function reviewIncorrect(Request $request)
    {
        $query = QuizAttemptAnswer::whereHas('attempt', function($q) {
            $q->where('user_id', Auth::id())
              ->whereNotNull('completed_at');
        })
        ->where('is_correct', false)
        ->with(['attempt.quiz', 'question.answers', 'answer']);

        // Filter by quiz
        if ($request->has('quiz_id') && $request->quiz_id) {
            $query->whereHas('attempt', function($q) use ($request) {
                $q->where('quiz_id', $request->quiz_id);
            });
        }

        // Filter by date range
        if ($request->has('date_from') && $request->date_from) {
            $query->whereHas('attempt', function($q) use ($request) {
                $q->whereDate('completed_at', '>=', $request->date_from);
            });
        }

        if ($request->has('date_to') && $request->date_to) {
            $query->whereHas('attempt', function($q) use ($request) {
                $q->whereDate('completed_at', '<=', $request->date_to);
            });
        }

        $incorrectAnswers = $query->orderBy('created_at', 'desc')->paginate(20);
        
        // Get all quizzes for filter
        $quizzes = Quiz::whereHas('attempts', function($q) {
            $q->where('user_id', Auth::id())
              ->whereNotNull('completed_at');
        })->orderBy('title')->get();

        return view('student.quizzes.review-incorrect', compact('incorrectAnswers', 'quizzes'));
    }

    /**
     * Retake a specific question from incorrect answers.
     *
     * @param  QuizQuestion  $question
     * @return \Illuminate\Http\RedirectResponse
     */
    public function retakeQuestion(QuizQuestion $question)
    {
        $quiz = $question->quiz;
        
        if (!$quiz || !$quiz->is_active) {
            return redirect()->route('student.quizzes.review-incorrect')
                ->with('error', 'Quiz is not available.');
        }

        return redirect()->route('student.quizzes.show', $quiz->id)
            ->with('focus_question', $question->id);
    }

    /**
     * Show performance analytics dashboard.
     *
     * @return \Illuminate\View\View
     */
    public function analytics()
    {
        $userId = Auth::id();
        
        // Overall statistics
        $totalAttempts = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->count();
        
        $totalQuizzes = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->distinct('quiz_id')
            ->count('quiz_id');
        
        $averageScore = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->avg('percentage');
        
        $totalQuestions = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->sum('total_questions');
        
        $totalCorrect = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->sum('correct_answers');
        
        $overallAccuracy = $totalQuestions > 0 ? ($totalCorrect / $totalQuestions) * 100 : 0;
        
        // Performance over time (last 30 days)
        $performanceData = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->where('completed_at', '>=', now()->subDays(30))
            ->orderBy('completed_at')
            ->get(['completed_at', 'percentage'])
            ->map(function($attempt) {
                return [
                    'date' => $attempt->completed_at->format('M d'),
                    'score' => $attempt->percentage
                ];
            });
        
        // Performance by quiz
        $quizPerformance = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->with('quiz')
            ->get()
            ->groupBy('quiz_id')
            ->map(function($attempts, $quizId) {
                $quiz = $attempts->first()->quiz;
                $bestScore = $attempts->max('percentage');
                $avgScore = $attempts->avg('percentage');
                $attemptCount = $attempts->count();
                
                return [
                    'quiz' => $quiz,
                    'best_score' => $bestScore,
                    'avg_score' => $avgScore,
                    'attempts' => $attemptCount
                ];
            })
            ->sortByDesc('best_score')
            ->take(10);
        
        // Performance by level
        $levelPerformance = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->with('quiz')
            ->get()
            ->groupBy(function($attempt) {
                return $attempt->quiz->level ?? 0;
            })
            ->map(function($attempts, $level) {
                $levelNames = [1 => 'Beginner', 2 => 'Intermediate', 3 => 'Advanced'];
                return [
                    'level' => $level,
                    'level_name' => $levelNames[$level] ?? 'Unknown',
                    'avg_score' => $attempts->avg('percentage'),
                    'attempts' => $attempts->count()
                ];
            });
        
        // Recent activity
        $recentAttempts = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->with('quiz')
            ->orderBy('completed_at', 'desc')
            ->take(10)
            ->get();
        
        // Weak areas (quizzes with lowest scores)
        $weakAreas = QuizAttempt::where('user_id', $userId)
            ->whereNotNull('completed_at')
            ->with('quiz')
            ->get()
            ->groupBy('quiz_id')
            ->map(function($attempts, $quizId) {
                $quiz = $attempts->first()->quiz;
                $avgScore = $attempts->avg('percentage');
                
                return [
                    'quiz' => $quiz,
                    'avg_score' => $avgScore
                ];
            })
            ->sortBy('avg_score')
            ->take(5);
        
        return view('student.quizzes.analytics', compact(
            'totalAttempts',
            'totalQuizzes',
            'averageScore',
            'overallAccuracy',
            'performanceData',
            'quizPerformance',
            'levelPerformance',
            'recentAttempts',
            'weakAreas'
        ));
    }

    /**
     * Toggle bookmark for a question.
     *
     * @param  QuizQuestion  $question
     * @return \Illuminate\Http\JsonResponse
     */
    public function toggleBookmark(QuizQuestion $question, Request $request)
    {
        $bookmark = QuestionBookmark::where('user_id', Auth::id())
            ->where('question_id', $question->id)
            ->first();

        if ($bookmark) {
            $bookmark->delete();
            $isBookmarked = false;
        } else {
            QuestionBookmark::create([
                'user_id' => Auth::id(),
                'question_id' => $question->id,
                'notes' => $request->input('notes'),
            ]);
            $isBookmarked = true;
        }

        return response()->json([
            'success' => true,
            'is_bookmarked' => $isBookmarked
        ]);
    }

    /**
     * Show all bookmarked questions.
     *
     * @param  Request  $request
     * @return \Illuminate\View\View
     */
    public function bookmarks(Request $request)
    {
        $query = QuestionBookmark::where('user_id', Auth::id())
            ->with(['question.quiz', 'question.answers']);

        // Filter by quiz
        if ($request->has('quiz_id') && $request->quiz_id) {
            $query->whereHas('question', function($q) use ($request) {
                $q->where('quiz_id', $request->quiz_id);
            });
        }

        $bookmarks = $query->orderBy('created_at', 'desc')->paginate(20);

        // Get all quizzes for filter
        $quizzes = Quiz::whereHas('questions.bookmarks', function($q) {
            $q->where('user_id', Auth::id());
        })->orderBy('title')->get();

        return view('student.quizzes.bookmarks', compact('bookmarks', 'quizzes'));
    }

    /**
     * Update bookmark notes.
     *
     * @param  QuestionBookmark  $bookmark
     * @param  Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateBookmarkNotes(QuestionBookmark $bookmark, Request $request)
    {
        if ($bookmark->user_id !== Auth::id()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $bookmark->update([
            'notes' => $request->input('notes')
        ]);

        return response()->json([
            'success' => true,
            'notes' => $bookmark->notes
        ]);
    }
}

