import React, { useState, useEffect } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import {
    MdAdd,
    MdEdit,
    MdEditOff,
    MdDelete,
} from 'react-icons/md';
import QuestionsList from '../Shared/QuestionsList';
import SortableQuestion from '../Shared/SortableQuestion';
import { DragEndEvent } from '@dnd-kit/core';
import Header from '../../Shared/Header';
import clsx from 'clsx';
import Alert, { AlertItem } from '../Shared/Alert';
import AutoExpandingTextArea from '@/components/Low/AutoExpandingTextarea';
import { ReadingPart, WriteBlanksExercise } from '@/interfaces/exam';
import useExamEditorStore from '@/stores/examEditor';
import useSectionEdit from '../../Hooks/useSectionEdit';
import setEditingAlert from '../Shared/setEditingAlert';
import { toast } from 'react-toastify';
import { validateEmptySolutions, validateQuestionText, validateWordCount } from './validation';
import { handleWriteBlanksReorder } from '@/stores/examEditor/reorder/local';
import { ParsedQuestion, parseText, reconstructText } from './parsing';
import PromptEdit from '../Shared/PromptEdit';


const WriteBlanks: React.FC<{ sectionId: number; exercise: WriteBlanksExercise; }> = ({ sectionId, exercise }) => {

    const { currentModule, dispatch } = useExamEditorStore();
    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 [editingPrompt, setEditingPrompt] = useState(false);
    const [errors, setErrors] = useState<{ [key: string]: string[] }>({});
    const [parsedQuestions, setParsedQuestions] = useState<ParsedQuestion[]>([]);

    const { editing, handleSave, handleDiscard, handleDelete, handlePractice, setEditing } = useSectionEdit({
        sectionId,
        onSave: () => {
            const isQuestionTextValid = validateQuestionText(
                parsedQuestions,
                setAlerts
            );

            const isSolutionsValid = validateEmptySolutions(
                local.solutions,
                setAlerts
            );

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

            setEditing(false);
            setAlerts([]);
            //dispatch({ type: 'UPDATE_ROOT', payload: { updates: {globalEdit: globalEdit.filter(id => id !== sectionId)} } });

            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: () => {
            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(() => {
        setParsedQuestions(parseText(local.text));
    }, [local.text]);

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

    const addQuestion = () => {
        const existingIds = parsedQuestions.map(q => parseInt(q.id));
        const newId = (Math.max(...existingIds, 0) + 1).toString();

        const newQuestion = {
            id: newId,
            questionText: "New question"
        };

        const updatedQuestions = [...parsedQuestions, newQuestion];
        const updatedText = reconstructText(updatedQuestions);

        const updatedSolutions = [...local.solutions, {
            id: newId,
            solution: [""]
        }];

        updateLocal({
            ...local,
            text: updatedText,
            solutions: updatedSolutions
        });
    };

    const updateQuestionText = (id: string, newText: string) => {
        const updatedQuestions = parsedQuestions.map(q =>
            q.id === id ? { ...q, questionText: newText } : q
        );
        const updatedText = reconstructText(updatedQuestions);
        updateLocal({ ...local, text: updatedText });
    };

    const deleteQuestion = (id: string) => {
        if (parsedQuestions.length == 1) {
            toast.error("There needs to be at least one question!");
            return;
        }
        const updatedQuestions = parsedQuestions.filter(q => q.id !== id);
        const updatedText = reconstructText(updatedQuestions);
        const updatedSolutions = local.solutions.filter(s => s.id !== id);
        updateLocal({
            ...local,
            text: updatedText,
            solutions: updatedSolutions
        });
    };

    const addSolutionToQuestion = (questionId: string) => {
        const newSolutions = [...local.solutions];
        const questionIndex = newSolutions.findIndex(s => s.id === questionId);

        if (questionIndex !== -1) {
            newSolutions[questionIndex] = {
                ...newSolutions[questionIndex],
                solution: [...newSolutions[questionIndex].solution, ""]
            };
            updateLocal({ ...local, solutions: newSolutions });
        }
    };

    const updateSolution = (questionId: string, solutionIndex: number, value: string) => {
        const wordCount = value.trim().split(/\s+/).length;

        const newSolutions = [...local.solutions];
        const questionIndex = newSolutions.findIndex(s => s.id === questionId);

        if (questionIndex !== -1) {
            const newSolutionArray = [...newSolutions[questionIndex].solution];
            newSolutionArray[solutionIndex] = value;
            newSolutions[questionIndex] = {
                ...newSolutions[questionIndex],
                solution: newSolutionArray
            };
            updateLocal({ ...local, solutions: newSolutions });
        }

        if (wordCount > local.maxWords) {
            setAlerts(prev => {
                const filteredAlerts = prev.filter(alert => alert.tag !== `solution-error-${questionId}-${solutionIndex}`);
                return [...filteredAlerts, {
                    variant: "error",
                    tag: `solution-error-${questionId}-${solutionIndex}`,
                    description: `Alternative solution ${solutionIndex + 1} for question ${questionId} exceeds maximum of ${local.maxWords} words (current: ${wordCount} words)`
                }];
            });
        } else {
            setAlerts(prev => prev.filter(alert => alert.tag !== `solution-error-${questionId}-${solutionIndex}`));
        }
    };

    const deleteSolution = (questionId: string, solutionIndex: number) => {
        const newSolutions = [...local.solutions];
        const questionIndex = newSolutions.findIndex(s => s.id === questionId);

        if (questionIndex !== -1) {
            if (newSolutions[questionIndex].solution.length == 1) {
                toast.error("There needs to be at least one solution!");
                return;
            }
            const newSolutionArray = newSolutions[questionIndex].solution.filter((_, i) => i !== solutionIndex);
            newSolutions[questionIndex] = {
                ...newSolutions[questionIndex],
                solution: newSolutionArray
            };
            updateLocal({ ...local, solutions: newSolutions });
        }
    };

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

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

    useEffect(() => {
        validateWordCount(local.solutions, local.maxWords, setAlerts);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [local.maxWords, local.solutions]);

    useEffect(() => {
        validateQuestionText(parsedQuestions, setAlerts);
    }, [parsedQuestions]);

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


    return (
        <div className="p-4">
            <Header
                title={"Write Blanks: Questions"}
                description="Edit questions and their solutions"
                editing={editing}
                handleSave={handleSave}
                handleDiscard={handleDiscard}
                handleDelete={handleDelete}
                handlePractice={handlePractice}
                isEvaluationEnabled={!local.isPractice}
            />
            <div className="space-y-4">
                {alerts.length > 0 && <Alert alerts={alerts} />}
                <Card className="mb-6">
                    <CardContent className="p-4 space-y-4">
                        <PromptEdit value={local.prompt} onChange={(prompt: string) => updateLocal({ ...local, prompt })} wrapperCard={false}/>
                        <div className="flex justify-between items-start gap-4">
                            <div className="flex items-center gap-4">
                                <label className="flex items-center gap-2">
                                    <span className="font-medium text-gray-800">Maximum words per solution:</span>
                                    <input
                                        type="number"
                                        value={local.maxWords}
                                        onChange={(e) => updateLocal({ ...local, maxWords: parseInt(e.target.value) })}
                                        className="w-20 p-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:outline-none"
                                        min="1"
                                    />
                                </label>
                            </div>
                        </div>
                    </CardContent>
                </Card>

                <div className="space-y-4">
                    <QuestionsList
                        ids={parsedQuestions.map(q => q.id)}
                        handleDragEnd={handleDragEnd}
                    >
                        {parsedQuestions.map((question) => {
                            const questionSolutions = local.solutions.find(s => s.id === question.id)?.solution || [];
                            return (
                                <SortableQuestion
                                    key={question.id}
                                    id={question.id}
                                    index={parseInt(question.id)}
                                    deleteQuestion={() => deleteQuestion(question.id)}
                                    variant="writeBlanks"
                                    questionText={question.questionText}
                                    onQuestionChange={(value) => updateQuestionText(question.id, value)}
                                >
                                    <div className="space-y-4">
                                        {questionSolutions.map((solution, solutionIndex) => (
                                            <div key={solutionIndex} className="flex gap-2">
                                                <input
                                                    type="text"
                                                    value={solution}
                                                    onChange={(e) => updateSolution(question.id, solutionIndex, e.target.value)}
                                                    className={clsx(
                                                        "flex-1 p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:outline-none",
                                                        errors[question.id]?.[solutionIndex] && "border-red-500"
                                                    )}
                                                    placeholder="Enter solution..."
                                                />
                                                <button
                                                    onClick={() => deleteSolution(question.id, solutionIndex)}
                                                    className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                                                >
                                                    <MdDelete size={20} className="text-gray-500" />
                                                </button>
                                            </div>
                                        ))}
                                        <button
                                            onClick={() => addSolutionToQuestion(question.id)}
                                            className="w-full p-2 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 Alternative Solution
                                        </button>
                                    </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>
        </div>
    );
};

export default WriteBlanks;
