import React, { useCallback, useEffect, useState } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import {
    MdAdd,
    MdEdit,
    MdEditOff,
} from 'react-icons/md';
import { ReadingPart, MultipleChoiceExercise, MultipleChoiceQuestion, LevelPart, ListeningPart, Difficulty } from '@/interfaces/exam';
import clsx from 'clsx';
import useExamEditorStore from '@/stores/examEditor';
import { toast } from 'react-toastify';
import { DragEndEvent } from '@dnd-kit/core';
import useSectionEdit from '@/components/ExamEditor/Hooks/useSectionEdit';
import Header from '@/components/ExamEditor/Shared/Header';
import Alert, { AlertItem } from '../../Shared/Alert';
import QuestionsList from '../../Shared/QuestionsList';
import SortableQuestion from '../../Shared/SortableQuestion';
import setEditingAlert from '../../Shared/setEditingAlert';
import { handleMultipleChoiceReorder } from '@/stores/examEditor/reorder/local';
import PromptEdit from '../../Shared/PromptEdit';
import { uuidv4 } from '@/utils/uuid';

interface MultipleChoiceProps {
    exercise: MultipleChoiceExercise;
    sectionId: number;
    optionsQuantity: number;
}

const validateMultipleChoiceQuestions = (
    questions: MultipleChoiceQuestion[], 
    optionsQuantity: number,
    setAlerts: React.Dispatch<React.SetStateAction<AlertItem[]>>
) => {
    const validationAlerts: AlertItem[] = [];
    
    questions.forEach((question, index) => {
        if (!question.prompt.trim()) {
            validationAlerts.push({
                variant: 'error',
                tag: `missing-prompt-${index}`,
                description: `Question ${index + 1} is missing a prompt`
            });
        }
        if (!question.solution) {
            validationAlerts.push({
                variant: 'error',
                tag: `missing-solution-${index}`,
                description: `Question ${index + 1} is missing a solution`
            });
        }
        if (question.options.length !== optionsQuantity) {
            validationAlerts.push({
                variant: 'error',
                tag: `invalid-options-${index}`,
                description: `Question ${index + 1} must have exactly ${optionsQuantity} options`
            });
        }
        question.options.forEach((option, optionIndex) => {
            if (option.text && option.text.trim() === "") {
                validationAlerts.push({
                    variant: 'error',
                    tag: `empty-option-${index}-${optionIndex}`,
                    description: `Question ${index + 1} has an empty option`
                });
            }
        });
    });

    setAlerts(prev => {
        const editingAlert = prev.find(alert => alert.tag === 'editing');
        return [...validationAlerts, ...(editingAlert ? [editingAlert] : [])];
    });

    return validationAlerts.length === 0;
};

const MultipleChoice: React.FC<MultipleChoiceProps> = ({ exercise, sectionId, optionsQuantity }) => {
    const { currentModule, dispatch } = useExamEditorStore();
    const difficulty = useExamEditorStore((state) => state.modules[currentModule].difficulty);
    const { state } = useExamEditorStore(
        (state) => state.modules[currentModule].sections.find((section) => section.sectionId === sectionId)!
    );

    const section = state as ReadingPart | ListeningPart| LevelPart;

    const [local, setLocal] = useState(exercise);
    const [editingPrompt, setEditingPrompt] = useState(false);
    const [alerts, setAlerts] = useState<AlertItem[]>([]);

    const updateLocal = (exercise: MultipleChoiceExercise) => {
        setLocal(exercise);
        setEditingAlert(true, setAlerts);
        setEditing(true);
    };

    const updateQuestion = (index: number, field: string, value: string) => {
        const newQuestions = [...local.questions];
        newQuestions[index] = { ...newQuestions[index], [field]: value };
        updateLocal({ ...local, questions: newQuestions });
    };

    const updateOption = (questionIndex: number, optionIndex: number, value: string) => {
        const newQuestions = [...local.questions];
        const newOptions = [...newQuestions[questionIndex].options];
        newOptions[optionIndex] = { ...newOptions[optionIndex], text: value };
        newQuestions[questionIndex] = { ...newQuestions[questionIndex], options: newOptions };
        updateLocal({ ...local, questions: newQuestions });
    };

    const addQuestion = () => {
        const newId = (parseInt(local.questions[local.questions.length - 1].id) + 1).toString();
        const options = Array.from({ length: optionsQuantity }, (_, i) => ({
            id: String.fromCharCode(65 + i),
            text: ''
        }));

        updateLocal({
            ...local,
            questions: [
                ...local.questions,
                {
                    prompt: "",
                    solution: "",
                    uuid: uuidv4(),
                    id: newId,
                    options,
                    variant: "text"
                },
            ]
        });
    };

    const deleteQuestion = (index: number) => {
        if (local.questions.length === 1) {
            toast.error("There needs to be at least one question!");
            return;
        }

        const newQuestions = local.questions.filter((_, i) => i !== index);
        const minId = Math.min(...newQuestions.map(q => parseInt(q.id)));
        
        const updatedQuestions = newQuestions.map((question, i) => ({
            ...question,
            id: String(minId + i)
        }));

        updateLocal({ ...local, questions: updatedQuestions });
    };

    const { editing, handleSave, handleDiscard, handleDelete, handlePractice, setEditing } = useSectionEdit({
        sectionId,
        onSave: () => {
            const isValid = validateMultipleChoiceQuestions(
                local.questions,
                optionsQuantity,
                setAlerts
            );

            if (!isValid) {
                toast.error("Please fix the errors before saving!");
                return;
            }

            setEditing(false);
            setAlerts([]);
            const newSection = {
                ...section,
                exercises: section.exercises.map((ex) => ex.id === local.id ? local : ex)
            };
            dispatch({ type: "UPDATE_SECTION_STATE", payload: { sectionId, update: newSection, module: currentModule } });
        },
        onDiscard: () => {
            setEditing(false);
            setAlerts([]);
            setLocal(exercise);
        },
        onDelete: () => {
            const newSection = {
                ...section,
                exercises: section.exercises.filter((ex) => ex.id !== local.id)
            };
            dispatch({ type: "UPDATE_SECTION_STATE", payload: { sectionId, update: newSection, module: currentModule } });
        },
        onPractice: () => {
            const updatedExercise = {
                ...local,
                isPractice: !local.isPractice
            };
            const newState = { ...section };
            newState.exercises = newState.exercises.map((ex) =>
                ex.id === exercise.id ? updatedExercise : ex
            );
            setLocal((prev) => ({...prev, isPractice: !local.isPractice}))
            dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } });
        }
    });

    useEffect(() => {
        validateMultipleChoiceQuestions(local.questions, optionsQuantity, setAlerts);
    }, [local.questions, optionsQuantity]);

    const handleDragEnd = (event: DragEndEvent) => {
        setEditingAlert(true, setAlerts);
        setEditing(true);
        setLocal(handleMultipleChoiceReorder(event, local));
    };

    const saveDifficulty = useCallback((diff: Difficulty) => {
        if (!difficulty.includes(diff)) {
            dispatch({ type: 'UPDATE_MODULE', payload: { updates: { difficulty: [...difficulty, diff]} } });
        }
        const updatedExercise = { ...exercise, difficulty: diff };
        const newState = { ...section };
        newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex );
        dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } });
    }, [currentModule, difficulty, dispatch, exercise, section, sectionId]);

    return (
        <div className="p-4">
            <Header
                title='Multiple Choice Exercise'
                description={`Edit questions with ${optionsQuantity} options each`}
                editing={editing}
                difficulty={exercise.difficulty}
                saveDifficulty={saveDifficulty}
                handleSave={handleSave}
                handleDelete={handleDelete}
                handleDiscard={handleDiscard}
                handlePractice={handlePractice}
                isEvaluationEnabled={!local.isPractice}
            />
            {alerts.length > 0 && <Alert className="mb-6" alerts={alerts} />}
            <PromptEdit value={local.prompt} onChange={(prompt: string) => updateLocal({...local, prompt})} />
            <div className="space-y-4">
                <QuestionsList
                    ids={local.questions.map(q => q.id)}
                    handleDragEnd={handleDragEnd}
                >
                    {local.questions.map((question, questionIndex) => (
                        <SortableQuestion
                            key={question.id}
                            id={question.id}
                            index={questionIndex}
                            deleteQuestion={deleteQuestion}
                        >
                            <div className="space-y-4">
                                <input
                                    type="text"
                                    value={question.prompt}
                                    onChange={(e) => updateQuestion(questionIndex, 'prompt', e.target.value)}
                                    className="w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:outline-none"
                                    placeholder="Enter question..."
                                />
                                <div className="space-y-2">
                                    {question.options.map((option, optionIndex) => (
                                        <div key={option.id} className="flex gap-2">
                                            <label
                                                className={clsx(
                                                    "flex-none w-12 p-3 text-center rounded-lg border-2 transition-all cursor-pointer",
                                                    question.solution === option.id
                                                        ? 'border-blue-500 bg-blue-50 text-blue-700'
                                                        : 'border-gray-200 hover:border-gray-300'
                                                )}
                                            >
                                                <input
                                                    type="radio"
                                                    name={`solution-${question.id}`}
                                                    value={option.id}
                                                    checked={question.solution === option.id}
                                                    onChange={(e) => updateQuestion(questionIndex, 'solution', e.target.value)}
                                                    className="sr-only"
                                                />
                                                {option.id}
                                            </label>
                                            <input
                                                type="text"
                                                value={option.text}
                                                onChange={(e) => updateOption(questionIndex, optionIndex, e.target.value)}
                                                className="flex-1 p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:outline-none"
                                                placeholder={`Option ${option.id}...`}
                                            />
                                        </div>
                                    ))}
                                </div>
                            </div>
                        </SortableQuestion>
                    ))}
                </QuestionsList>

                <button
                    onClick={addQuestion}
                    className="w-full p-4 border-2 border-dashed border-gray-300 rounded-lg hover:border-blue-500 hover:bg-blue-50 transition-colors flex items-center justify-center gap-2 text-gray-600 hover:text-blue-600"
                >
                    <MdAdd size={18} />
                    Add New Question
                </button>
            </div>
        </div>
    );
};

export default MultipleChoice;
