<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

use App\Models\BankQuestion;
use App\Models\MultipleChoice;
use App\Models\ShortAnswer;


class QuestionController extends Controller
{
    public function store(Request $request)
    {

        $user = auth()->user();

        if (!$user) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthenticated'
            ], 401);
        }

        $request->validate([
            'category_id' => 'required|integer',
            'sub_category_id' => 'required|integer',
            'question_type' => 'required|in:multiple_choice,short_answer',
            'question' => 'required|string',
        ]);

        if ($request->question_type === 'multiple_choice') {

            $request->validate([
                'option_a' => 'required',
                'option_b' => 'required',
                'option_c' => 'required',
                'option_d' => 'required',
                'correct_answer' => 'required|in:A,B,C,D'
            ]);
        }

        if ($request->question_type === 'short_answer') {
            $request->validate([
                'correct_answer' => 'required'
            ]);
        }

        \Log::info($request->all());

        DB::beginTransaction();

        try {

            $questionBank = BankQuestion::create([
                'category_id' => $request->category_id,
                'sub_category_id' => $request->sub_category_id,
                'question_type' => $request->question_type,
                'created_by' => $user->user_id
            ]);

            if ($request->question_type === 'multiple_choice') {

                MultipleChoice::create([
                    'question_id' => $questionBank->id,
                    'question' => $request->question,
                    'option_a' => $request->option_a,
                    'option_b' => $request->option_b,
                    'option_c' => $request->option_c,
                    'option_d' => $request->option_d,
                    'correct_answer' => $request->correct_answer,
                    'image' => $request->image,
                    'explanation' => $request->explanation,
                    'created_by' => $user->user_id
                ]);
            }

            if ($request->question_type === 'short_answer') {

                ShortAnswer::create([
                    'question_id'       => $questionBank->id,
                    'question'          => $request->question,
                    'correct_answer'    => $request->correct_answer,
                    'image'             => $request->image,
                    'explanation'       => $request->explanation,
                    'created_by'        => $user->user_id
                ]);
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Question saved successfully',
                'question_id' => $questionBank->id
            ]);
        }
        catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function getMultipleChoiceQuestions(Request $request)
    {
        $query = DB::table('bank_questions as bq')
            ->join(
                'multiple_choice as mc',
                'bq.id',
                '=',
                'mc.question_id'
            )
            ->join(
                'categories as c',
                'bq.category_id',
                '=',
                'c.id'
            )
            ->join(
                'sub_categories as sc',
                'bq.sub_category_id',
                '=',
                'sc.id'
            )
            ->select(
                'bq.id',
                'c.name as category_name',
                'sc.name as sub_category_name',
                'mc.question',
                'mc.option_a',
                'mc.option_b',
                'mc.option_c',
                'mc.option_d',
                'mc.correct_answer',
                'mc.explanation',
                'mc.image',
                'bq.created_at'
            );

        if ($request->filled('category_id')) {
            $query->where(
                'bq.category_id',
                $request->category_id
            );
        }

        if ($request->filled('sub_category_id')) {
            $query->where(
                'bq.sub_category_id',
                $request->sub_category_id
            );
        }

        $questions = $query
            ->orderByDesc('bq.id')
            ->get();

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

    public function uploadMultipleChoiceCsv(Request $request)
    {
        $request->validate([
            'category_id'     => 'required|integer',
            'sub_category_id' => 'required|integer',
            'file'            => 'required|file|mimes:csv,txt'
        ]);

        $file = $request->file('file');

        $handle = fopen($file->getRealPath(), 'r');

        if (!$handle) {
            return response()->json([
                'success' => false,
                'message' => 'Unable to read CSV file'
            ], 400);
        }

        $header = fgetcsv($handle);

        $totalRows = 0;
        $successRows = 0;
        $errors = [];

        DB::beginTransaction();

        try {

            while (($row = fgetcsv($handle)) !== false) {

                $totalRows++;

                if (count($row) < 7) {
                    $errors[] = "Row {$totalRows} invalid format";
                    continue;
                }

                $question       = trim($row[0]);
                $optionA        = trim($row[1]);
                $optionB        = trim($row[2]);
                $optionC        = trim($row[3]);
                $optionD        = trim($row[4]);
                $correctAnswer  = strtoupper(trim($row[5]));
                $explanation    = trim($row[6]);

                if (
                    empty($question) ||
                    empty($optionA) ||
                    empty($optionB) ||
                    empty($optionC) ||
                    empty($optionD)
                ) {
                    $errors[] = "Row {$totalRows} has empty mandatory field";
                    continue;
                }

                if (!in_array($correctAnswer, ['A', 'B', 'C', 'D'])) {
                    $errors[] = "Row {$totalRows} invalid correct answer";
                    continue;
                }

                $questionId = DB::table('bank_questions')
                    ->insertGetId([
                        'category_id'     => $request->category_id,
                        'sub_category_id' => $request->sub_category_id,
                        'question_type'   => 'multiple_choice',
                        'created_by'      => auth()->user()->user_id ?? 'system',
                        'created_at'      => now()
                    ]);

                DB::table('multiple_choice')
                    ->insert([
                        'question_id'    => $questionId,
                        'question'       => $question,
                        'option_a'       => $optionA,
                        'option_b'       => $optionB,
                        'option_c'       => $optionC,
                        'option_d'       => $optionD,
                        'correct_answer' => $correctAnswer,
                        'explanation'    => $explanation,
                        'created_by'     => auth()->user()->user_id ?? 'system',
                        'created_at'     => now()
                    ]);

                $successRows++;
            }

            fclose($handle);

            DB::commit();

            return response()->json([
                'success'       => true,
                'total_rows'    => $totalRows,
                'success_rows'  => $successRows,
                'failed_rows'   => count($errors),
                'errors'        => $errors
            ]);

        } catch (\Exception $e) {

            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function getShortAnswerQuestions(Request $request)
    {
        $query = DB::table('bank_questions as bq')
            ->join(
                'short_answer as sa',
                'bq.id',
                '=',
                'sa.question_id'
            )
            ->join(
                'categories as c',
                'bq.category_id',
                '=',
                'c.id'
            )
            ->join(
                'sub_categories as sc',
                'bq.sub_category_id',
                '=',
                'sc.id'
            )
            ->select(
                'bq.id',
                'c.name as category_name',
                'sc.name as sub_category_name',
                'sa.question',
                'sa.correct_answer',
                'sa.explanation',
                'sa.image',
                'bq.created_at'
            );

        if ($request->filled('category_id')) {
            $query->where(
                'bq.category_id',
                $request->category_id
            );
        }

        if ($request->filled('sub_category_id')) {
            $query->where(
                'bq.sub_category_id',
                $request->sub_category_id
            );
        }

        $questions = $query
            ->orderByDesc('bq.id')
            ->get();

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

    public function uploadShortAnswerCsv(Request $request)
    {
        $request->validate([
            'category_id'     => 'required|integer',
            'sub_category_id' => 'required|integer',
            'file'            => 'required|file|mimes:csv,txt'
        ]);

        $file = $request->file('file');

        $handle = fopen($file->getRealPath(), 'r');

        if (!$handle) {
            return response()->json([
                'success' => false,
                'message' => 'Unable to read CSV file'
            ], 400);
        }

        $header = array_map(
            'trim',
            fgetcsv($handle)
        );

        $expectedHeader = [
            'question',
            'correct_answer',
            'explanation'
        ];

        if ($header !== $expectedHeader) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid CSV format'
            ], 400);
        }

        $totalRows = 0;
        $successRows = 0;
        $errors = [];

        DB::beginTransaction();

        try {

            while (($row = fgetcsv($handle)) !== false) {

                $totalRows++;

                if (count($row) < 3) {
                    $errors[] = "Row {$totalRows} invalid format";
                    continue;
                }

                $question      = trim($row[0]);
                $correctAnswer = trim($row[1]);
                $explanation   = trim($row[2]);

                if (
                    empty($question) ||
                    empty($correctAnswer)
                ) {
                    $errors[] = "Row {$totalRows} has empty mandatory field";
                    continue;
                }

                $questionId = DB::table('bank_questions')
                    ->insertGetId([
                        'category_id'     => $request->category_id,
                        'sub_category_id' => $request->sub_category_id,
                        'question_type'   => 'short_answer',
                        'created_by'      => auth()->id() ?? 'system',
                        'created_at'      => now()
                    ]);

                DB::table('short_answer')
                    ->insert([
                        'question_id'    => $questionId,
                        'question'       => $question,
                        'correct_answer' => $correctAnswer,
                        'explanation'    => $explanation,
                        'created_by'     => auth()->id() ?? 'system',
                        'created_at'     => now()
                    ]);

                $successRows++;
            }

            fclose($handle);

            DB::commit();

            return response()->json([
                'success'       => true,
                'total_rows'    => $totalRows,
                'success_rows'  => $successRows,
                'failed_rows'   => count($errors),
                'errors'        => $errors
            ]);

        } catch (\Exception $e) {

            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function destroy($id)
    {
        DB::beginTransaction();

        try {

            $question = DB::table('bank_questions')
                ->where('id', $id)
                ->first();

            if (!$question) {
                return response()->json([
                    'success' => false,
                    'message' => 'Question not found'
                ], 404);
            }

            if ($question->question_type === 'multiple_choice') {

                DB::table('multiple_choice')
                    ->where('question_id', $id)
                    ->delete();
            }

            if ($question->question_type === 'short_answer') {

                DB::table('short_answer')
                    ->where('question_id', $id)
                    ->delete();
            }

            DB::table('bank_questions')
                ->where('id', $id)
                ->delete();

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Question deleted successfully'
            ]);

        } catch (\Exception $e) {

            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    } 

    public function update(Request $request, $id)
    {
        DB::beginTransaction();

        try {

            $question = DB::table('bank_questions')
                ->where('id', $id)
                ->first();

            if (!$question) {
                return response()->json([
                    'success' => false,
                    'message' => 'Question not found'
                ], 404);
            }

            if ($question->question_type === 'short_answer') {

                DB::table('short_answer')
                    ->where('question_id', $id)
                    ->update([
                        'question'       => $request->question,
                        'correct_answer' => $request->correct_answer,
                        'explanation'    => $request->explanation,
                        'updated_at'     => now()
                    ]);
            }

            if ($question->question_type === 'multiple_choice') {

                DB::table('multiple_choice')
                    ->where('question_id', $id)
                    ->update([
                        'question'       => $request->question,
                        'option_a'       => $request->option_a,
                        'option_b'       => $request->option_b,
                        'option_c'       => $request->option_c,
                        'option_d'       => $request->option_d,
                        'correct_answer' => $request->correct_answer,
                        'explanation'    => $request->explanation,
                        'updated_at'     => now()
                    ]);
            }

            DB::table('bank_questions')
                ->where('id', $id)
                ->update([
                    'category_id'     => $request->category_id,
                    'sub_category_id' => $request->sub_category_id,
                    'updated_at'      => now()
                ]);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Question updated successfully'
            ]);

        } catch (\Exception $e) {

            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function quizMultipleChoice(Request $request)
    {
        $categoryId = $request->category_id;
        $subCategoryId = $request->sub_category_id;

        $questions = DB::table('bank_questions as bq')
            ->join(
                'multiple_choice as mc',
                'bq.id',
                '=',
                'mc.question_id'
            )
            ->where('bq.category_id', $categoryId)
            ->where('bq.sub_category_id', $subCategoryId)
            ->select(
                'bq.id',
                'mc.question',
                'mc.option_a',
                'mc.option_b',
                'mc.option_c',
                'mc.option_d',
                'mc.correct_answer',
                'mc.explanation',
                'mc.image'
            )
            ->inRandomOrder()
            ->get();

        return response()->json($questions);
    }

}