import {ChangeEvent, RefObject, useContext, useEffect, useRef, useState} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
    faBookBookmark,
    faBookOpen,
    faChartSimple,
    faChevronRight,
    faClock,
    faCloudSun,
    faComments,
    faFileLines,
    faGraduationCap,
    faLanguage,
    faMagicWandSparkles,
    faMusic,
    faPencilAlt,
    faRotateRight,
    faSpinner,
    faStop,
    faUserAstronaut,
    faUserEdit,
    faX
} from "@fortawesome/free-solid-svg-icons";
import {writingLevel} from "@/lib/models/User";
import Story, {
    advancedDialogueTypes,
    advancedNarrativePersons,
    advancedPredefinedType,
    beginnerDialogueTypes,
    beginnerNarrativePersons,
    beginnerPredefinedType,
    intermediateDialogueTypes,
    intermediateNarrativePersons,
    intermediatePredefinedType,
    langues,
    verbalTime
} from '@/lib/models/Story';
import SelectBox from "@/components/form/SelectBox";
import TextInput from "@/components/form/TextInput";
import TexteAreaInput from "@/components/form/TexteAreaInput";
import {SessionContext} from "@/context/SessionContext";
import System from "@/lib/models/System";
import {AlertContext} from "@/context/AlertContext";
import {configs} from "@/lib/configs";
import InputField from "@/components/form/InputField";
import NumberInput from "@/components/form/NumberInput";
import {Editor as TipEditor, EditorContent, useEditor} from "@tiptap/react";
import Editor from "@/lib/models/Editor";
import StarterKit from "@tiptap/starter-kit";
import Underline from "@tiptap/extension-underline";
import TextAlign from "@tiptap/extension-text-align";
import QuillSense from "@/lib/models/QuillSense";
import {useTranslations} from "next-intl";
import {LangContext, LangContextProps} from "@/context/LangContext";
import {AIUsageContext, AIUsageContextProps} from "@/context/AIUsageContext";
import AdvancedGenerationOptions from "@/components/form/AdvancedGenerationOptions";

interface ShortStoryGeneratorProps {
    onClose: () => void;
}

export default function ShortStoryGenerator({onClose}: ShortStoryGeneratorProps) {
    const {session} = useContext(SessionContext);
    const {errorMessage, infoMessage} = useContext(AlertContext);
    const {lang} = useContext<LangContextProps>(LangContext)
    const t = useTranslations();
    const {setTotalPrice, setTotalCredits} = useContext<AIUsageContextProps>(AIUsageContext)
    
    const [tone, setTone] = useState<string>('');
    const [atmosphere, setAtmosphere] = useState<string>('');
    const [verbTense, setVerbTense] = useState<string>('0');
    const [person, setPerson] = useState<string>('0');
    const [characters, setCharacters] = useState<string>('');
    const [language, setLanguage] = useState<string>(
        session.user?.writingLang.toString() ?? '0',
    );
    const [dialogueType, setDialogueType] = useState<string>('0');
    const [wordsCount, setWordsCount] = useState<number>(500)
    const [directives, setDirectives] = useState<string>('');
    const [authorLevel, setAuthorLevel] = useState<string>(
        session.user?.writingLevel.toString() ?? '0',
    );
    const [presetType, setPresetType] = useState<string>('0');

    const [activeTab, setActiveTab] = useState<number>(1);
    const [progress, setProgress] = useState<number>(25);
    const modalRef: RefObject<HTMLDivElement | null> = useRef<HTMLDivElement>(null);
    const [isGenerating, setIsGenerating] = useState<boolean>(false);

    const [generatedText, setGeneratedText] = useState<string>('');
    const [generatedStoryTitle, setGeneratedStoryTitle] = useState<string>('');
    const [resume, setResume] = useState<string>('');
    const [totalWordsCount, setTotalWordsCount] = useState<number>(0);

    const [hasGenerated, setHasGenerated] = useState<boolean>(false);
    const [abortController, setAbortController] = useState<ReadableStreamDefaultReader<Uint8Array> | null>(null);
    
    const [useExplicit, setUseExplicit] = useState<boolean>(false);
    const [useSmart, setUseSmart] = useState<boolean>(false);
    
    const isAnthropicEnabled: boolean = QuillSense.isAnthropicEnabled(session);
    const isSubTierTwo: boolean = QuillSense.getSubLevel(session) >= 2;
    const hasAccess: boolean = isAnthropicEnabled || isSubTierTwo;
    
    const editor: TipEditor | null = useEditor({
        extensions: [
            StarterKit,
            Underline,
            TextAlign.configure({
                types: ['heading', 'paragraph'],
            }),
        ],
        injectCSS: false,
        immediatelyRender: false,
    });
    
    useEffect((): () => void => {
        document.body.style.overflow = 'hidden';
        return (): void => {
            document.body.style.overflow = 'auto';
        };
    }, []);
    
    useEffect((): void => {
        Story.presetStoryType(
            presetType,
            setTone,
            setAtmosphere,
            setVerbTense,
            setPerson,
            setDialogueType,
            (): void => {
            },
        );
    }, [presetType]);
    
    useEffect((): void => {
        setProgress(activeTab * 25);
    }, [activeTab]);
    
    useEffect((): void => {
        if (editor)
            editor.commands.setContent(Editor.convertToHtml(generatedText))
        getWordCount();
    }, [editor, generatedText]);
    
    async function handleStopGeneration(): Promise<void> {
        if (abortController) {
            await abortController.cancel();
            setAbortController(null);
            infoMessage(t("shortStoryGenerator.result.abortSuccess"));
        }
    }
    
    async function handleGeneration(): Promise<void> {
        setIsGenerating(true);
        setGeneratedText('');
        
        try {
            const response: Response = await fetch(`${configs.apiUrl}quillsense/generate/short`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${session.accessToken}`,
                },
                body: JSON.stringify({
                    authorLevel: authorLevel,
                    tone: tone,
                    atmosphere: atmosphere,
                    verbTense: verbTense,
                    person: person,
                    characters: characters,
                    language: language,
                    dialogueType: dialogueType,
                    directives: directives,
                    wordsCount: wordsCount,
                    useExplicit: useExplicit,
                    useSmart: useSmart,
                }),
            });
            
            if (!response.ok) {
                const error: { message?: string } = await response.json();
                errorMessage(error.message || t("shortStoryGenerator.result.unknownError"));
                setIsGenerating(false);
                return;
            }
            setActiveTab(4);
            setProgress(100);
            
            const reader: ReadableStreamDefaultReader<Uint8Array> | undefined = response.body?.getReader();
            const decoder: TextDecoder = new TextDecoder();
            let accumulatedText: string = '';
            
            if (!reader) {
                errorMessage(t("shortStoryGenerator.result.noResponse"));
                setIsGenerating(false);
                return;
            }
            
            setAbortController(reader);
            
            while (true) {
                try {
                    const {done, value}: ReadableStreamReadResult<Uint8Array> = await reader.read();
                    
                    if (done) break;
                    
                    const chunk: string = decoder.decode(value, {stream: true});
                    const lines: string[] = chunk.split('\n');
                    
                    for (const line of lines) {
                        if (line.startsWith('data: ')) {
                            try {
                                const data: {
                                    content?: string;
                                    title?: string;
                                    useYourKey?: boolean;
                                    totalPrice?: number;
                                    totalCost?: number;
                                } = JSON.parse(line.slice(6));
                                
                                if (data.content && data.content !== 'starting') {
                                    accumulatedText += data.content;
                                    setGeneratedText(accumulatedText);
                                }
                                
                                if (data.title && data.useYourKey !== undefined && data.totalPrice !== undefined) {
                                    setGeneratedStoryTitle(data.title);
                                    if (data.useYourKey) {
                                        setTotalPrice((prev: number): number => prev + data.totalPrice!);
                                    } else {
                                        setTotalCredits(data.totalPrice);
                                    }
                                }
                            } catch (e: unknown) {
                                errorMessage(t("shortStoryGenerator.result.parsingError"));
                            }
                        }
                    }
                } catch (e: unknown) {
                    break;
                }
            }
            
            setIsGenerating(false);
            setHasGenerated(true);
            setAbortController(null);
        } catch (e: unknown) {
            if (e instanceof Error) {
                if (e.name !== 'AbortError') {
                    errorMessage(e.message);
                }
            } else {
                errorMessage(t("shortStoryGenerator.result.unknownError"));
            }
            setIsGenerating(false);
            setAbortController(null);
        }
    }

    function getWordCount(): void {
        if (editor) {
            try {
                const content: string = editor?.state.doc.textContent;
                const texteNormalise: string = content
                    .replace(/'/g, ' ')
                    .replace(/-/g, ' ')
                    .replace(/\s+/g, ' ')
                    .trim();
                const mots: string[] = texteNormalise.split(' ');
                const wordCount: number = mots.filter(
                    (mot: string): boolean => mot.length > 0,
                ).length;
                setTotalWordsCount(wordCount);
            } catch (e: unknown) {
                if (e instanceof Error) {
                    errorMessage(e.message);
                } else {
                    errorMessage(t("shortStoryGenerator.result.unknownError"));
                }
            }
        }
    }

    async function handleSave(): Promise<void> {
        let content: string = '';
        if (editor) content = editor?.state?.doc.toJSON();
        try {
            const bookId: string = await System.authPostToServer<string>(
                `quillsense/generate/add`,
                {
                    title: generatedStoryTitle,
                    resume: resume,
                    content: content,
                    wordCount: totalWordsCount,
                    tone: tone,
                    atmosphere: atmosphere,
                    verbTense: verbTense,
                    language: language,
                    dialogueType: dialogueType,
                    person: person,
                    authorLevel: authorLevel
                        ? authorLevel
                        : session.user?.writingLevel,
                },
                session.accessToken,
                lang
            );
            if (!bookId) {
                errorMessage(t("shortStoryGenerator.result.saveError"));
                return;
            }
            onClose();
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("shortStoryGenerator.result.unknownError"));
            }
        }
    }

    if (!hasAccess) {
        return (
            <div
                className="fixed inset-0 flex items-center justify-center bg-darkest-background/80 z-50 backdrop-blur-sm">
                <div
                    className="bg-dark-background text-text-primary rounded-lg border border-secondary shadow-xl w-full max-w-md p-6">
                    <h2 className="flex items-center font-['ADLaM_Display'] text-xl text-text-primary mb-4">
                        <FontAwesomeIcon icon={faMagicWandSparkles} className="mr-3 w-5 h-5"/>
                        {t("shortStoryGenerator.accessDenied.title")}
                    </h2>
                    <p className="text-text-secondary mb-6">
                        {t("shortStoryGenerator.accessDenied.message")}
                    </p>
                    <button
                        onClick={onClose}
                        className="w-full bg-primary text-text-primary px-4 py-2 rounded-lg hover:bg-primary-dark transition-colors"
                    >
                        {t("shortStoryGenerator.accessDenied.close")}
                    </button>
                </div>
            </div>
        );
    }
    
    return (
        <div className="fixed inset-0 flex items-center justify-center bg-overlay z-40 backdrop-blur-sm">
            <div ref={modalRef}
                 className="bg-tertiary/90 backdrop-blur-sm text-text-primary rounded-2xl border border-secondary/50 shadow-2xl w-full max-w-4xl max-h-[90vh] flex flex-col">
                
                <div className="flex justify-between items-center bg-primary px-6 py-4 rounded-t-2xl shadow-md">
                    <h2 className="font-['ADLaM_Display'] text-xl text-text-primary flex items-center">
                        <FontAwesomeIcon icon={faMagicWandSparkles} className="mr-3 w-5 h-5"/>
                        {t("shortStoryGenerator.title")}
                    </h2>
                    <button
                        className="text-text-primary hover:bg-primary-dark p-2 rounded-xl transition-all duration-200 hover:scale-110"
                        onClick={onClose}
                        disabled={isGenerating}
                    >
                        <FontAwesomeIcon icon={faX} className="w-5 h-5"/>
                    </button>
                </div>
                
                <div className="px-6 py-4 border-b border-secondary/50">
                    <div className="w-full bg-secondary/50 rounded-full h-2.5 shadow-inner">
                        <div
                            className="bg-primary h-2.5 rounded-full transition-all duration-300 shadow-sm"
                            style={{width: `${progress}%`}}
                        />
                    </div>
                </div>
                
                <div className="flex border-b border-secondary/50">
                    {[
                        {id: 1, label: t("shortStoryGenerator.tabs.basics"), icon: faBookOpen},
                        {id: 2, label: t("shortStoryGenerator.tabs.structure"), icon: faUserEdit},
                        {id: 3, label: t("shortStoryGenerator.tabs.atmosphere"), icon: faCloudSun},
                        ...(hasGenerated || isGenerating ? [{
                            id: 4,
                            label: t("shortStoryGenerator.tabs.result"),
                            icon: faFileLines
                        }] : [])
                    ].map(tab => (
                        <button
                            key={tab.id}
                            onClick={() => setActiveTab(tab.id)}
                            disabled={isGenerating}
                            className={`flex items-center px-6 py-3 font-medium transition-colors ${
                                activeTab === tab.id
                                    ? 'text-primary border-b-2 border-primary bg-primary/5'
                                    : 'text-text-secondary hover:text-text-primary'
                            }`}
                        >
                            <FontAwesomeIcon icon={tab.icon} className="mr-2 w-4 h-4"/>
                            {tab.label}
                            {tab.id === 4 && isGenerating && !generatedText && (
                                <FontAwesomeIcon icon={faSpinner} className="ml-2 animate-spin w-4 h-4"/>
                            )}
                        </button>
                    ))}
                </div>
                
                <div className="flex-1">
                    {activeTab === 1 && (
                        <div className="p-6 space-y-6">
                            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                                <InputField
                                    icon={faGraduationCap}
                                    fieldName={t("shortStoryGenerator.fields.complexity")}
                                    input={
                                        <SelectBox
                                            onChangeCallBack={(e) => setAuthorLevel(e.target.value)}
                                            data={writingLevel}
                                            defaultValue={authorLevel}
                                        />
                                    }
                                />
                                <InputField
                                    icon={faBookOpen}
                                    fieldName={t("shortStoryGenerator.fields.preset")}
                                    input={
                                        <SelectBox
                                            onChangeCallBack={(e) => setPresetType(e.target.value)}
                                            data={
                                                authorLevel === '1'
                                                    ? beginnerPredefinedType
                                                    : authorLevel === '2'
                                                        ? intermediatePredefinedType
                                                        : advancedPredefinedType
                                            }
                                            defaultValue={presetType}
                                        />
                                    }
                                />
                                <InputField
                                    icon={faLanguage}
                                    fieldName={t("shortStoryGenerator.fields.language")}
                                    input={
                                        <SelectBox
                                            onChangeCallBack={(e) => setLanguage(e.target.value)}
                                            data={langues}
                                            defaultValue={language}
                                        />
                                    }
                                />
                                <InputField
                                    icon={faChartSimple}
                                    fieldName={t("shortStoryGenerator.fields.wordCount")}
                                    input={
                                        <NumberInput
                                            value={wordsCount}
                                            setValue={setWordsCount}
                                            placeholder="500"
                                        />
                                    }
                                />
                            </div>
                        </div>
                    )}
                    
                    {activeTab === 2 && (
                        <div className="p-6 space-y-6">
                            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                                <InputField
                                    icon={faClock}
                                    fieldName={t("shortStoryGenerator.fields.tense")}
                                    input={
                                        <SelectBox
                                            onChangeCallBack={(e) => setVerbTense(e.target.value)}
                                            data={verbalTime}
                                            defaultValue={verbTense}
                                        />
                                    }
                                />
                                <InputField
                                    icon={faUserEdit}
                                    fieldName={t("shortStoryGenerator.fields.narrative")}
                                    input={
                                        <SelectBox
                                            onChangeCallBack={(e) => setPerson(e.target.value)}
                                            data={
                                                authorLevel === '1'
                                                    ? beginnerNarrativePersons
                                                    : authorLevel === '2'
                                                        ? intermediateNarrativePersons
                                                        : advancedNarrativePersons
                                            }
                                            defaultValue={person}
                                        />
                                    }
                                />
                            </div>
                            
                            <InputField
                                icon={faComments}
                                fieldName={t("shortStoryGenerator.fields.dialogue")}
                                input={
                                    <SelectBox
                                        onChangeCallBack={(e) => setDialogueType(e.target.value)}
                                        data={
                                            authorLevel === '1'
                                                ? beginnerDialogueTypes
                                                : authorLevel === '2'
                                                    ? intermediateDialogueTypes
                                                    : advancedDialogueTypes
                                        }
                                        defaultValue={dialogueType}
                                    />
                                }
                            />
                            
                            <InputField
                                icon={faPencilAlt}
                                fieldName={t("shortStoryGenerator.fields.directives")}
                                input={
                                    <TexteAreaInput
                                        value={directives}
                                        setValue={(e: ChangeEvent<HTMLTextAreaElement>) => setDirectives(e.target.value)}
                                        placeholder={t("shortStoryGenerator.placeholders.directives")}
                                    />
                                }
                            />
                        </div>
                    )}
                    
                    {activeTab === 3 && (
                        <div className="p-6 space-y-6">
                            <div className="space-y-4">
                                <InputField
                                    icon={faMusic}
                                    fieldName={t("shortStoryGenerator.fields.tone")}
                                    input={
                                        <TextInput
                                            value={tone}
                                            setValue={(e: ChangeEvent<HTMLInputElement>) => setTone(e.target.value)}
                                            placeholder={t("shortStoryGenerator.placeholders.tone")}
                                        />
                                    }
                                />
                            </div>
                            
                            <div className="space-y-4">
                                <InputField
                                    icon={faCloudSun}
                                    fieldName={t("shortStoryGenerator.fields.atmosphere")}
                                    input={
                                        <TextInput
                                            value={atmosphere}
                                            setValue={(e: ChangeEvent<HTMLInputElement>) => setAtmosphere(e.target.value)}
                                            placeholder={t("shortStoryGenerator.placeholders.atmosphere")}
                                        />
                                    }
                                />
                            </div>
                            
                            <InputField
                                icon={faUserAstronaut}
                                fieldName={t("shortStoryGenerator.fields.character")}
                                input={
                                    <TextInput
                                        value={characters}
                                        setValue={(e: ChangeEvent<HTMLInputElement>) => setCharacters(e.target.value)}
                                        placeholder={t("shortStoryGenerator.placeholders.character")}
                                    />
                                }
                            />
                            
                            <AdvancedGenerationOptions
                                useExplicit={useExplicit}
                                setUseExplicit={setUseExplicit}
                                useSmart={useSmart}
                                setUseSmart={setUseSmart}
                            />
                        </div>
                    )}
                    
                    {activeTab === 4 && (
                        <div className="p-6">
                            <div className="flex justify-between items-center mb-4">
                                <h3 className="font-semibold text-lg">
                                    {generatedStoryTitle || t("shortStoryGenerator.result.title")}
                                </h3>
                                
                                <div className="flex items-center space-x-2">
                                    {isGenerating ? (
                                        <button
                                            onClick={handleStopGeneration}
                                            className="p-2 rounded-xl bg-red-500 hover:bg-red-600 transition-all duration-200 hover:scale-110 shadow-md"
                                            title={t("shortStoryGenerator.actions.stop")}
                                        >
                                            <FontAwesomeIcon icon={faStop} className="w-4 h-4"/>
                                        </button>
                                    ) : generatedText && (
                                        <>
                                            <button
                                                onClick={handleGeneration}
                                                className="p-2 rounded-xl bg-secondary/50 hover:bg-secondary transition-all duration-200 hover:scale-110 shadow-sm border border-secondary/50"
                                                title={t("shortStoryGenerator.actions.regenerate")}
                                            >
                                                <FontAwesomeIcon icon={faRotateRight} className="w-4 h-4"/>
                                            </button>
                                            <button
                                                onClick={handleSave}
                                                className="p-2 rounded-xl bg-primary hover:bg-primary-dark transition-all duration-200 hover:scale-110 shadow-md"
                                                title={t("shortStoryGenerator.actions.save")}
                                            >
                                                <FontAwesomeIcon icon={faBookBookmark} className="w-4 h-4"/>
                                            </button>
                                        </>
                                    )}
                                </div>
                            </div>
                            
                            {isGenerating && !generatedText ? (
                                <div className="flex flex-col items-center justify-center py-20">
                                    <FontAwesomeIcon icon={faSpinner}
                                                     className="animate-spin text-primary mb-4 w-8 h-8"/>
                                    <p className="text-text-secondary">{t("shortStoryGenerator.result.generating")}</p>
                                </div>
                            ) : (
                                <div
                                    className="bg-darkest-background rounded-lg p-6 overflow-auto max-h-96 fade-in-text">
                                    <EditorContent editor={editor} className="prose prose-invert max-w-none"/>
                                </div>
                            )}
                            
                            {generatedText && (
                                <div className="flex justify-between items-center mt-4 pt-4 border-t border-secondary">
                                    <div className="flex items-center text-sm text-text-secondary">
                                        <FontAwesomeIcon icon={faChartSimple} className="mr-2 w-4 h-4"/>
                                        {totalWordsCount} {t("shortStoryGenerator.result.words")}
                                    </div>
                                </div>
                            )}
                        </div>
                    )}
                </div>
                
                <div
                    className="flex justify-between items-center p-6 border-t border-secondary/50 bg-secondary/30 backdrop-blur-sm shadow-inner">
                    <button
                        onClick={() => setActiveTab(Math.max(1, activeTab - 1))}
                        className={`px-4 py-2 rounded-xl transition-all duration-200 flex items-center ${
                            activeTab > 1 && !isGenerating
                                ? 'text-text-secondary hover:text-text-primary hover:bg-secondary hover:scale-105 shadow-sm'
                                : 'text-muted cursor-not-allowed'
                        }`}
                        disabled={activeTab === 1 || isGenerating}
                    >
                        <FontAwesomeIcon icon={faChevronRight} className="mr-2 rotate-180 w-4 h-4"/>
                        {t("shortStoryGenerator.navigation.previous")}
                    </button>
                    
                    <div className="flex items-center space-x-3">
                        <button
                            onClick={onClose}
                            className="px-6 py-2.5 rounded-xl bg-secondary/50 text-text-primary hover:bg-secondary transition-all duration-200 hover:scale-105 shadow-sm border border-secondary/50 font-medium"
                            disabled={isGenerating}
                        >
                            {activeTab === 4 && hasGenerated ? t("shortStoryGenerator.navigation.close") : t("shortStoryGenerator.navigation.cancel")}
                        </button>
                        
                        {activeTab < 3 ? (
                            <button
                                onClick={() => setActiveTab(activeTab + 1)}
                                disabled={isGenerating}
                                className="px-6 py-2.5 rounded-xl bg-primary text-text-primary hover:bg-primary-dark transition-all duration-200 hover:scale-105 flex items-center disabled:opacity-50 shadow-md hover:shadow-lg font-medium"
                            >
                                {t("shortStoryGenerator.navigation.next")}
                                <FontAwesomeIcon icon={faChevronRight} className="ml-2 w-4 h-4"/>
                            </button>
                        ) : activeTab === 3 && (
                            <button
                                onClick={handleGeneration}
                                disabled={isGenerating}
                                className="px-6 py-2.5 rounded-xl bg-primary text-text-primary hover:bg-primary-dark transition-all duration-200 hover:scale-105 flex items-center disabled:opacity-50 shadow-md hover:shadow-lg font-medium"
                            >
                                {isGenerating ? (
                                    <>
                                        <FontAwesomeIcon icon={faSpinner} className="animate-spin mr-2 w-4 h-4"/>
                                        {t("shortStoryGenerator.actions.generating")}
                                    </>
                                ) : (
                                    <>
                                        <FontAwesomeIcon icon={faMagicWandSparkles} className="mr-2 w-4 h-4"/>
                                        {t("shortStoryGenerator.actions.generate")}
                                    </>
                                )}
                            </button>
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
}