import useSectionEdit from "@/components/ExamEditor/Hooks/useSectionEdit";
import { Card, CardContent } from "@/components/ui/card";
import { WriteBlanksExercise, ReadingPart, Difficulty } from "@/interfaces/exam";
import useExamEditorStore from "@/stores/examEditor";
import { useState, useReducer, useEffect, useCallback } from "react";
import { toast } from "react-toastify";
import BlanksEditor from "..";
import { AlertItem } from "../../Shared/Alert";
import setEditingAlert from "../../Shared/setEditingAlert";
import { blanksReducer } from "../BlanksReducer";
import { validateWriteBlanks } from "./validation";
import AlternativeSolutions from "./AlternativeSolutions";

const WriteBlanksFill: React.FC<{ exercise: WriteBlanksExercise; sectionId: number }> = ({ exercise, sectionId }) => {
    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;

    const [alerts, setAlerts] = useState<AlertItem[]>([]);
    const [local, setLocal] = useState(exercise);
    const [selectedBlankId, setSelectedBlankId] = useState<string | null>(null);
    const [editing, setEditing] = useState(false);

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

    const [blanksState, blanksDispatcher] = useReducer(blanksReducer, {
        text: exercise.text || "",
        blanks: [],
        selectedBlankId: null,
        draggedItemId: null,
        textMode: false,
        setEditing,
    });

    const { handleSave, handleDiscard, handleDelete, handlePractice } = useSectionEdit({
        sectionId,
        editing,
        setEditing,
        onSave: () => {
            if (!validateWriteBlanks(local.solutions, local.maxWords, setAlerts)) {
                toast.error("Please fix the errors before saving!");
                return;
            }

            setEditing(false);
            setAlerts([]);

            const updatedExercise = {
                ...local,
                text: blanksState.text,
            };

            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 } });
        },
        onDiscard: () => {
            setSelectedBlankId(null);
            setLocal(exercise);
            blanksDispatcher({ type: "RESET", payload: { text: exercise.text } });
        },
        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(() => {
        if (!editing) {
            setLocal(exercise);
        }
    }, [exercise, editing]);

    const handleAddSolution = (blankId: string) => {
        if (!editing) setEditing(true);
        setLocal(prev => ({
            ...prev,
            solutions: prev.solutions.map(s =>
                s.id === blankId
                    ? { ...s, solution: [...s.solution, ""] }
                    : s
            )
        }));
    };

    const handleRemoveSolution = (blankId: string, index: number) => {
        if (!editing) setEditing(true);

        const solutions = local.solutions.find(s => s.id === blankId);
        if (solutions && solutions.solution.length <= 1) {
            toast.error("Each blank must have at least one solution!");
            return;
        }

        setLocal(prev => ({
            ...prev,
            solutions: prev.solutions.map(s =>
                s.id === blankId
                    ? { ...s, solution: s.solution.filter((_, i) => i !== index) }
                    : s
            )
        }));
    };

    const handleEditSolution = (blankId: string, index: number, value: string) => {
        if (!editing) setEditing(true);

        setLocal(prev => ({
            ...prev,
            solutions: prev.solutions.map(s =>
                s.id === blankId
                    ? {
                        ...s,
                        solution: s.solution.map((sol, i) => i === index ? value : sol)
                    }
                    : s
            )
        }));
    };

    const handleBlankRemove = (blankId: number) => {
        if (!editing) setEditing(true);
        setLocal(prev => ({
            ...prev,
            solutions: prev.solutions.filter(s => s.id !== blankId.toString())
        }));

        blanksDispatcher({ type: "REMOVE_BLANK", payload: blankId });
    };

    useEffect(() => {
        validateWriteBlanks(local.solutions, local.maxWords, setAlerts);
    }, [local.solutions, local.maxWords]);

    useEffect(() => {
        setEditingAlert(editing, setAlerts);
    }, [editing]);

    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="space-y-4">
            <BlanksEditor
                title="Write Blanks: Fill"
                alerts={alerts}
                editing={editing}
                state={blanksState}
                blanksDispatcher={blanksDispatcher}
                description={local.prompt}
                initialText={local.text}
                difficulty={exercise.difficulty}
                saveDifficulty={saveDifficulty}
                module={currentModule}
                showBlankBank={true}
                onBlankSelect={(blankId) => setSelectedBlankId(blankId?.toString() || null)}
                onBlankRemove={handleBlankRemove}
                onSave={handleSave}
                onDiscard={handleDiscard}
                onDelete={handleDelete}
                onPractice={handlePractice}
                setEditing={setEditing}
                isEvaluationEnabled={!local.isPractice}
                prompt={local.prompt}
                updatePrompt={(prompt: string) => updateLocal({ ...local, prompt })}
            >
                {!blanksState.textMode && (
                    <Card>
                        <CardContent className="p-4">
                            <div className="flex items-center justify-between mb-4">
                                <span className="text-lg font-semibold">
                                    {selectedBlankId
                                        ? `Solutions for Blank ${selectedBlankId}`
                                        : "Click a blank to edit its solutions"}
                                </span>
                                {selectedBlankId && (
                                    <span className="text-sm text-gray-500">
                                        Max words per solution: {local.maxWords}
                                    </span>
                                )}
                            </div>

                            <div className="grid grid-cols-1 gap-4">
                                {selectedBlankId && (
                                    <AlternativeSolutions
                                        solutions={local.solutions.find(s => s.id === selectedBlankId)?.solution || []}
                                        onAdd={() => handleAddSolution(selectedBlankId)}
                                        onRemove={(index: number) => handleRemoveSolution(selectedBlankId, index)}
                                        onEdit={(index: number, value: string) => handleEditSolution(selectedBlankId, index, value)}
                                    />
                                )}
                            </div>
                        </CardContent>
                    </Card>
                )}
            </BlanksEditor>
        </div>
    );
};

export default WriteBlanksFill;