import Dropdown from "../Shared/SettingsDropdown";
import ExercisePicker from "../../ExercisePicker";
import GenerateBtn from "../Shared/GenerateBtn";
import { useCallback } from "react";
import { generate } from "../Shared/Generate";
import { LevelSectionSettings, ListeningSectionSettings } from "@/stores/examEditor/types";
import useExamEditorStore from "@/stores/examEditor";
import { LevelPart, ListeningPart } from "@/interfaces/exam";
import Input from "@/components/Low/Input";
import axios from "axios";
import { toast } from "react-toastify";
import { playSound } from "@/utils/sound";

interface Props {
    localSettings: ListeningSectionSettings | LevelSectionSettings;
    updateLocalAndScheduleGlobal: (updates: Partial<ListeningSectionSettings | LevelSectionSettings>, schedule?: boolean) => void;
    currentSection: ListeningPart | LevelPart;
    audioContextDisabled?: boolean;
    levelId?: number;
    level?: boolean;
}

const ListeningComponents: React.FC<Props> = ({ currentSection, localSettings, updateLocalAndScheduleGlobal, levelId, level = false, audioContextDisabled = false }) => {
    const { currentModule, dispatch, modules } = useExamEditorStore();
    const {
        focusedSection,
        difficulty,
    } = useExamEditorStore(state => state.modules[currentModule]);

    const generateScript = useCallback(() => {
        generate(
            levelId ? levelId : focusedSection,
            "listening",
            "listeningScript",
            {
                method: 'GET',
                queryParams: {
                    difficulty,
                    ...(localSettings.listeningTopic && { topic: localSettings.listeningTopic })
                }
            },
            (data: any) => [{
                script: data.dialog
            }],
            level ? focusedSection : undefined,
            level
        );
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [localSettings.listeningTopic, difficulty, focusedSection, levelId, level]);

    const onTopicChange = useCallback((listeningTopic: string) => {
        updateLocalAndScheduleGlobal({ listeningTopic });
    }, [updateLocalAndScheduleGlobal]);


    const generateAudio = useCallback(async (sectionId: number) => {
        let body: any;
        if ([1, 3].includes(levelId ? levelId : focusedSection)) {
            body = { conversation: currentSection.script }
        } else {
            body = { monologue: currentSection.script }
        }

        try {
            if (level) {
                dispatch({
                    type: "UPDATE_SECTION_SINGLE_FIELD", payload: {
                        sectionId, module: "level", field: "levelGenerating", value:
                            [...modules["level"].sections.find((s) => s.sectionId === sectionId)!.levelGenerating, "audio"]
                    }
                });
            } else {
                dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { sectionId, module: currentModule, field: "generating", value: "audio" } });
            }

            const response = await axios.post(
                '/api/exam/media/listening',
                body,
                {
                    responseType: 'arraybuffer',
                    headers: {
                        'Accept': 'audio/mpeg'
                    },
                }
            );

            const blob = new Blob([response.data], { type: 'audio/mpeg' });
            const url = URL.createObjectURL(blob);

            if (currentSection.audio?.source) {
                URL.revokeObjectURL(currentSection.audio?.source)
            }

            dispatch({
                type: "UPDATE_SECTION_STATE",
                payload: {
                    sectionId,
                    module: level ? "level" : "listening",
                    update: {
                        audio: {
                            source: url,
                            repeatableTimes: 3
                        }
                    }
                }
            });
            playSound("check");
            toast.success('Audio generated successfully!');
        } catch (error: any) {
            toast.error('Failed to generate audio');
        } finally {
            if (level) {
                dispatch({
                    type: "UPDATE_SECTION_SINGLE_FIELD", payload: {
                        sectionId, module: "level", field: "levelGenerating", value:
                            [...modules["level"].sections.find((s) => s.sectionId === sectionId)!.levelGenerating.filter(g => g !== "audio")]
                    }
                });
            } else {
                dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { sectionId, module: currentModule, field: "generating", value: undefined } });
            }
        }

        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentSection?.script, dispatch, level, levelId]);

    return (
        <>
            <Dropdown
                title="Audio Context"
                module="listening"
                open={localSettings.isAudioContextOpen}
                disabled={audioContextDisabled}
                setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isAudioContextOpen: isOpen }, false)}
                contentWrapperClassName={level ? `border border-ielts-listening` : ''}
            >
                <div className="flex flex-row gap-2 items-center px-2 pb-4">
                    <div className="flex flex-col flex-grow gap-4 px-2">
                        <label className="font-normal text-base text-mti-gray-dim">Topic (Optional)</label>
                        <Input
                            key={`section-${focusedSection}`}
                            type="text"
                            placeholder="Topic"
                            name="category"
                            onChange={onTopicChange}
                            roundness="full"
                            value={localSettings.listeningTopic}
                        />
                    </div>
                    <div className="flex self-end h-16 mb-1">
                        <GenerateBtn
                            module="listening"
                            genType="listeningScript"
                            sectionId={focusedSection}
                            generateFnc={generateScript}
                            level={level}
                        />
                    </div>
                </div>
            </Dropdown>
            <Dropdown
                title="Add Exercises"
                module="listening"
                open={localSettings.isListeningTopicOpen}
                setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isListeningTopicOpen: isOpen }, false)}
                disabled={currentSection === undefined || currentSection.script === undefined && currentSection.audio === undefined}
                contentWrapperClassName={level ? `border border-ielts-listening` : ''}
            >
                <ExercisePicker
                    module="listening"
                    sectionId={levelId !== undefined ? levelId : focusedSection}
                    difficulty={difficulty}
                    extraArgs={{ script: currentSection === undefined || currentSection.audio === undefined ? "" : currentSection.script }}
                    levelSectionId={focusedSection}
                    level={level}
                />
            </Dropdown>

            <Dropdown
                title="Generate Audio"
                module="listening"
                open={localSettings.isAudioGenerationOpen}
                setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isAudioGenerationOpen: isOpen }, false)}
                disabled={currentSection === undefined || currentSection.script === undefined && currentSection.audio === undefined || currentSection.exercises.length === 0}
                contentWrapperClassName={level ? `border border-ielts-listening` : ''}
            >
                <div className="flex flex-row items-center text-mti-gray-dim justify-center mb-4 gap-2 p-2">
                    <span className="bg-gray-100 px-3.5 py-2.5 rounded-lg border border-gray-300">
                        Generate audio recording for this section
                    </span>
                    <GenerateBtn
                        module="listening"
                        genType="audio"
                        sectionId={levelId ? levelId : focusedSection}
                        generateFnc={generateAudio}
                    />
                </div>
            </Dropdown>
        </>
    );
};

export default ListeningComponents;