import EXERCISES from "./exercises";
import clsx from "clsx";
import { ExerciseGen, GeneratedExercises, GeneratorState } from "./generatedExercises";
import Modal from "@/components/Modal";
import { useCallback, useState } from "react";
import ExerciseWizard, { ExerciseConfig } from "./ExerciseWizard";
import { generate } from "../SettingsEditor/Shared/Generate";
import { Module } from "@/interfaces";
import useExamEditorStore from "@/stores/examEditor";
import { LevelPart, ListeningPart, Message, ReadingPart } from "@/interfaces/exam";
import { BsArrowRepeat } from "react-icons/bs";

interface ExercisePickerProps {
    module: string;
    sectionId: number;
    difficulty: string;
    extraArgs?: Record<string, any>;
    levelSectionId?: number;
    level?: boolean;
}

const ExercisePicker: React.FC<ExercisePickerProps> = ({
    module,
    sectionId,
    extraArgs = undefined,
    levelSectionId,
    level = false
}) => {
    const { currentModule, dispatch } = useExamEditorStore();
    const { difficulty, sections } = useExamEditorStore((store) => store.modules[level ? "level" : currentModule]);
    const section = sections.find((s) => s.sectionId === (level ? levelSectionId : sectionId));

    const [pickerOpen, setPickerOpen] = useState(false);
    const [localSelectedExercises, setLocalSelectedExercises] = useState<string[]>([]);

    const state = section?.state;

    const getFullExerciseType = (exercise: ExerciseGen): string => {
        if (exercise.extra && exercise.extra.length > 0) {
            const extraValue = exercise.extra.find(e => e.param === 'name')?.value;
            return extraValue ? `${exercise.type}/?name=${extraValue}` : exercise.type;
        }
        return exercise.type;
    };

    const handleChange = (exercise: ExerciseGen) => {
        const fullType = getFullExerciseType(exercise);

        setLocalSelectedExercises(prev => {
            const newSelected = prev.includes(fullType)
                ? prev.filter(type => type !== fullType)
                : [...prev, fullType];
            return newSelected;
        });
    };

    const moduleExercises = (sectionId && !["level", "writing", "speaking"].includes(module) ? EXERCISES.filter((ex) => ex.module === module && ex.sectionId == sectionId) : EXERCISES.filter((ex) => ex.module === module));

    const onModuleSpecific = useCallback((configurations: ExerciseConfig[]) => {
        const exercises = configurations.map(config => {
            const exerciseType = config.type.split('name=')[1];
            return {
                type: exerciseType,
                quantity: Number(config.params.quantity || 1),
                ...(config.params.num_random_words !== undefined && {
                    num_random_words: Number(config.params.num_random_words)
                }),
                ...(config.params.max_words !== undefined && {
                    max_words: Number(config.params.max_words)
                })
            };
        });

        let context = {};
        if (module === 'reading') {
            const readingState = state as ReadingPart | LevelPart;
            context = {
                text: readingState.text!.content
            };
        } else if (module === 'listening') {
            const listeningState = state as ListeningPart | LevelPart;
            const script = listeningState.script;
            if (sectionId === 1 || sectionId === 3) {
                const dialog = script as Message[];
                context = {
                    text: dialog.map((d) => `${d.name}: ${d.text}`).join("\n")
                };
            } else if (sectionId === 2 || sectionId === 4) {
                context = {
                    text: script as string
                };
            }
        }
        if (!["speaking", "writing"].includes(module)) {
            generate(
                sectionId,
                module as Module,
                level ? `exercises-${module}` : "exercises",
                {
                    method: 'POST',
                    body: {
                        ...context,
                        exercises: exercises,
                        difficulty: difficulty
                    }
                },
                (data: any) => [{
                    exercises: data.exercises
                }],
                levelSectionId,
                level
            );
        } else if (module === "writing") {
            configurations.forEach((config) => {
                let queryParams = config.params.topic !== '' ? { topic: config.params.topic as string } : undefined;
                generate(
                    config.type === 'writing_letter' ? 1 : 2,
                    "writing",
                    config.type,
                    {
                        method: 'GET',
                        queryParams
                    },
                    (data: any) => [{
                        prompt: data.question
                    }],
                    levelSectionId,
                    level
                );
            });
        } else {
            configurations.forEach((config) => {
                let queryParams = Object.fromEntries(
                    Object.entries({
                        topic: config.params.topic as string,
                        first_topic: config.params.first_topic as string,
                        second_topic: config.params.second_topic as string,
                    }).filter(([_, value]) => value && value !== '')
                );
                let query = Object.keys(queryParams).length === 0 ? undefined : queryParams;
                generate(
                    Number(config.type.split('_')[1]),
                    "speaking",
                    config.type,
                    {
                        method: 'GET',
                        queryParams: query
                    },
                    (data: any) => {
                        switch (Number(config.type.split('_')[1])) {
                            case 1:
                                return [{
                                    prompts: data.questions,
                                    first_topic: data.first_topic,
                                    second_topic: data.second_topic
                                }];
                            case 2:
                                return [{
                                    topic: data.topic,
                                    question: data.question,
                                    prompts: data.prompts,
                                    suffix: data.suffix
                                }];
                            case 3:
                                return [{
                                    topic: data.topic,
                                    questions: data.questions
                                }];
                            default:
                                return [data];
                        }
                    },
                    levelSectionId,
                    level
                );
            });
        }
        setLocalSelectedExercises([]);
        setPickerOpen(false);
    }, [
        sectionId,
        levelSectionId,
        level,
        module,
        state,
        difficulty,
        setPickerOpen
    ]);

    if (section === undefined) return <></>;

    return (
        <>
            <Modal isOpen={pickerOpen} onClose={() => setPickerOpen(false)} title="Exercise Wizard"
                titleClassName={clsx(
                    "text-2xl font-semibold text-center py-4",
                    `bg-ielts-${module} text-white`,
                    "shadow-sm",
                    "-mx-6 -mt-6",
                    "mb-6"
                )}
            >
                <ExerciseWizard
                    module={module as Module}
                    selectedExercises={localSelectedExercises}
                    sectionId={sectionId}
                    exercises={moduleExercises}
                    onSubmit={onModuleSpecific}
                    onDiscard={() => setPickerOpen(false)}
                    extraArgs={extraArgs}
                />
            </Modal>
            <div className="flex flex-col gap-4 px-4" key={sectionId}>
                <div className="space-y-2">
                    {moduleExercises.map((exercise) => {
                        const fullType = getFullExerciseType(exercise);
                        return (
                            <label
                                key={fullType}
                                className={`flex items-center space-x-3 text-white font-semibold cursor-pointer p-2 hover:bg-ielts-${exercise.module}/70 rounded bg-ielts-${exercise.module}/90`}
                            >
                                <input
                                    type="checkbox"
                                    name="exercise"
                                    value={fullType}
                                    checked={localSelectedExercises.includes(fullType)}
                                    onChange={() => handleChange(exercise)}
                                    className="h-5 w-5"
                                />
                                <div className="flex items-center space-x-2">
                                    <exercise.icon className="h-5 w-5 text-white" />
                                    <span>{exercise.label}</span>
                                </div>
                            </label>
                        );
                    })}
                </div>
                <div className="flex flex-row justify-center">
                    <button
                        className={
                            clsx("flex items-center justify-center px-4 py-2 text-white rounded-xl transition-colors duration-300 disabled:cursor-not-allowed",
                                `bg-ielts-${module}/70 border border-ielts-${module} hover:bg-ielts-${module} disabled:bg-ielts-${module}/40 `,
                            )
                        }
                        onClick={() => setPickerOpen(true)}
                        disabled={localSelectedExercises.length === 0}
                    >
                        {section.generating === "exercises" ? (
                            <div key={`section-${sectionId}`} className="flex items-center justify-center">
                                <BsArrowRepeat className="text-white animate-spin" size={25} />
                            </div>
                        ) : (
                            <>{["speaking", "writing"].includes(module) ? "Add Exercises" : "Set Up Exercises"} ({localSelectedExercises.length})  </>
                        )}
                    </button>
                </div>
            </div>
        </>
    );
};

export default ExercisePicker;