'use client'
import {ChangeEvent, Dispatch, SetStateAction, useContext, useEffect, useRef, useState} from "react";
import {AlertContext} from "@/context/AlertContext";
import System from "@/lib/models/System";
import {SessionContext} from "@/context/SessionContext";
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
    faBook,
    faBookOpen,
    faCalendarAlt,
    faFileWord,
    faInfo,
    faPencilAlt,
    faX
} from "@fortawesome/free-solid-svg-icons";
import {SelectBoxProps} from "@/shared/interface";
import {BookProps, bookTypes} from "@/lib/models/Book";
import InputField from "@/components/form/InputField";
import TextInput from "@/components/form/TextInput";
import SelectBox from "@/components/form/SelectBox";
import DatePicker from "@/components/form/DatePicker";
import NumberInput from "@/components/form/NumberInput";
import TexteAreaInput from "@/components/form/TexteAreaInput";
import CancelButton from "@/components/form/CancelButton";
import SubmitButtonWLoading from "@/components/form/SubmitButtonWLoading";
import GuideTour, {GuideStep} from "@/components/GuideTour";
import {UserProps} from "@/lib/models/User";
import {useTranslations} from "next-intl";
import {LangContext, LangContextProps} from "@/context/LangContext";
import {getOfflineDataService} from "@/lib/services/offline-data.service";

interface MinMax {
    min: number;
    max: number;
}

export default function AddNewBookForm({setCloseForm}: { setCloseForm: Dispatch<SetStateAction<boolean>> }) {
    const t = useTranslations();
    const {lang} = useContext<LangContextProps>(LangContext);
    const {session, setSession} = useContext(SessionContext);
    const {errorMessage} = useContext(AlertContext);
    const modalRef: React.RefObject<HTMLDivElement | null> = useRef<HTMLDivElement>(null);
    
    const [title, setTitle] = useState<string>('');
    const [subtitle, setSubtitle] = useState<string>('');
    const [summary, setSummary] = useState<string>('');
    const [publicationDate, setPublicationDate] = useState<string>('');
    const [wordCount, setWordCount] = useState<number>(0);
    const [selectedBookType, setSelectedBookType] = useState<string>('');
    
    const [isAddingBook, setIsAddingBook] = useState<boolean>(false);
    const [bookTypeHint, setBookTypeHint] = useState<boolean>(false);
    
    const token: string = session?.accessToken ?? '';
    
    const bookTypesHint: GuideStep[] = [{
        id: 0,
        x: 80,
        y: 50,
        title: t("addNewBookForm.bookTypeHint.title"),
        content: (
            <div className="space-y-4 max-h-96 overflow-y-auto custom-scrollbar">
                <div className="space-y-3">
                    <div className="border-l-4 border-primary pl-4 bg-secondary/10 p-3 rounded-r-xl">
                        <h4 className="font-semibold text-lg text-text-primary mb-1">{t("addNewBookForm.bookTypeHint.nouvelle.title")}</h4>
                        <p className="text-sm text-muted mb-2">{t("addNewBookForm.bookTypeHint.nouvelle.range")}</p>
                        <p className="text-sm text-text-secondary">{t("addNewBookForm.bookTypeHint.nouvelle.description")}</p>
                    </div>
                    <div className="border-l-4 border-primary pl-4 bg-secondary/10 p-3 rounded-r-xl">
                        <h4 className="font-semibold text-lg text-text-primary mb-1">{t("addNewBookForm.bookTypeHint.novelette.title")}</h4>
                        <p className="text-sm text-muted mb-2">{t("addNewBookForm.bookTypeHint.novelette.range")}</p>
                        <p className="text-sm text-text-secondary">{t("addNewBookForm.bookTypeHint.novelette.description")}</p>
                    </div>
                    <div className="border-l-4 border-primary pl-4 bg-secondary/10 p-3 rounded-r-xl">
                        <h4 className="font-semibold text-lg text-text-primary mb-1">{t("addNewBookForm.bookTypeHint.novella.title")}</h4>
                        <p className="text-sm text-muted mb-2">{t("addNewBookForm.bookTypeHint.novella.range")}</p>
                        <p className="text-sm text-text-secondary">{t("addNewBookForm.bookTypeHint.novella.description")}</p>
                    </div>
                    <div className="border-l-4 border-primary pl-4 bg-secondary/10 p-3 rounded-r-xl">
                        <h4 className="font-semibold text-lg text-text-primary mb-1">{t("addNewBookForm.bookTypeHint.chapbook.title")}</h4>
                        <p className="text-sm text-muted mb-2">{t("addNewBookForm.bookTypeHint.chapbook.range")}</p>
                        <p className="text-sm text-text-secondary">{t("addNewBookForm.bookTypeHint.chapbook.description")}</p>
                    </div>
                    <div className="border-l-4 border-primary pl-4 bg-secondary/10 p-3 rounded-r-xl">
                        <h4 className="font-semibold text-lg text-text-primary mb-1">{t("addNewBookForm.bookTypeHint.roman.title")}</h4>
                        <p className="text-sm text-muted mb-2">{t("addNewBookForm.bookTypeHint.roman.range")}</p>
                        <p className="text-sm text-text-secondary">{t("addNewBookForm.bookTypeHint.roman.description")}</p>
                    </div>
                </div>
                <div className="bg-primary/10 border border-primary/30 p-4 rounded-xl">
                    <p className="text-sm text-text-primary font-medium">
                        {t("addNewBookForm.bookTypeHint.tip")}
                    </p>
                </div>
            </div>
        ),
    }]
    
    useEffect((): () => void => {
        document.body.style.overflow = 'hidden';
        return (): void => {
            document.body.style.overflow = 'auto';
        };
    }, []);
    
    async function handleAddBook(): Promise<void> {
        if (!title) {
            errorMessage(t('addNewBookForm.error.titleMissing'));
            return;
        } else {
            if (title.length < 2) {
                errorMessage(t('addNewBookForm.error.titleTooShort'));
                return;
            }
            if (title.length > 50) {
                errorMessage(t('addNewBookForm.error.titleTooLong'));
                return;
            }
        }
        if (selectedBookType === '') {
            errorMessage(t('addNewBookForm.error.typeMissing'));
            return;
        }
        setIsAddingBook(true);
        try {
            const offlineDataService = getOfflineDataService();
            const bookData = {
                title,
                subTitle: subtitle,
                type: selectedBookType,
                summary,
                serie: 0,
                publicationDate,
                desiredWordCount: wordCount
            };

            const bookId: string = await offlineDataService.createBook(
                bookData,
                session.user?.id || '',
                async () => {
                    // Only called if online
                    const id = await System.authPostToServer<string>('book/add', {
                        title: title,
                        subTitle: subtitle,
                        type: selectedBookType,
                        summary: summary,
                        serie: 0,
                        publicationDate: publicationDate,
                        desiredWordCount: wordCount,
                    }, token, lang);
                    if (!id) {
                        throw new Error(t('addNewBookForm.error.addingBook'));
                    }
                    return id;
                }
            );

            const book: BookProps = {
                bookId: bookId,
                ...bookData
            };

            setSession({
                ...session,
                user: {
                    ...session.user as UserProps,
                    books: [...((session.user as UserProps)?.books ?? []), book]
                }
            });
            setIsAddingBook(false);
            setCloseForm(false)
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('addNewBookForm.error.addingBook'));
            }
            setIsAddingBook(false);
        }
    }
    
    function maxWordsCountHint(): MinMax {
        switch (selectedBookType) {
            case 'short':
                return {
                    min: 1000,
                    max: 7500,
                };
            case 'chapbook':
                return {
                    min: 1000,
                    max: 10000,
                };
            case 'novelette' :
                return {
                    min: 7500,
                    max: 17500,
                };
            case 'long' :
                return {
                    min: 17500,
                    max: 40000,
                };
            case 'novel' :
                return {
                    min: 40000,
                    max: 0,
                };
            default :
                return {
                    min: 0,
                    max: 0
                }
        }
    }
    
    return (
        <div
            className="fixed inset-0 flex items-center justify-center bg-black/60 z-50 backdrop-blur-md animate-fadeIn">
            <div ref={modalRef}
                 className="bg-tertiary/95 backdrop-blur-sm text-text-primary rounded-2xl border border-secondary/50 shadow-2xl md:w-3/4 xl:w-1/4 lg:w-2/4 sm:w-11/12 max-h-[85vh] flex flex-col">
                <div className="flex justify-between items-center bg-primary px-6 py-4 rounded-t-2xl shadow-lg">
                    <h2 className="flex items-center gap-3 font-['ADLaM_Display'] text-2xl text-text-primary">
                        <FontAwesomeIcon icon={faBook} className="w-6 h-6"/>
                        {t("addNewBookForm.title")}
                    </h2>
                    <button
                        className="text-background hover:text-background w-10 h-10 rounded-xl hover:bg-white/20 transition-all duration-200 flex items-center justify-center hover:scale-110"
                        onClick={(): void => setCloseForm(false)}
                    >
                        <FontAwesomeIcon icon={faX} className={'w-5 h-5'}/>
                    </button>
                </div>
                
                <div className="p-5 overflow-y-auto flex-grow custom-scrollbar">
                    <div className="space-y-6">
                        <InputField icon={faBookOpen} fieldName={t("addNewBookForm.type")} input={
                            <SelectBox
                                onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => setSelectedBookType(e.target.value)}
                                data={bookTypes.map((types: SelectBoxProps): SelectBoxProps => {
                                    return {
                                        value: types.value,
                                        label: t(types.label)
                                    }
                                })} defaultValue={selectedBookType}
                                placeholder={t("addNewBookForm.typePlaceholder")}/>
                        } action={async (): Promise<void> => setBookTypeHint(true)} actionIcon={faInfo}/>
                        <InputField icon={faPencilAlt} fieldName={t("addNewBookForm.bookTitle")} input={
                            <TextInput value={title}
                                       setValue={(e: ChangeEvent<HTMLInputElement>): void => setTitle(e.target.value)}
                                       placeholder={t("addNewBookForm.bookTitlePlaceholder")}/>
                        }/>
                        {
                            selectedBookType !== 'lyric' && (
                                <InputField icon={faPencilAlt} fieldName={t("addNewBookForm.subtitle")} input={
                                    <TextInput value={subtitle}
                                               setValue={(e: ChangeEvent<HTMLInputElement>): void => setSubtitle(e.target.value)}
                                               placeholder={t("addNewBookForm.subtitlePlaceholder")}/>
                                }/>
                            )
                        }
                        
                        <InputField icon={faCalendarAlt} fieldName={t("addNewBookForm.publicationDate")} input={
                            <DatePicker date={publicationDate}
                                        setDate={(e: React.ChangeEvent<HTMLInputElement>): void => setPublicationDate(e.target.value)}/>
                        }/>
                        
                        {
                            selectedBookType !== 'lyric' && (
                                <>
                                    <InputField icon={faFileWord} fieldName={t("addNewBookForm.wordGoal")}
                                                hint={selectedBookType && `${maxWordsCountHint().min.toLocaleString('fr-FR')} - ${maxWordsCountHint().max > 0 ? maxWordsCountHint().max.toLocaleString('fr-FR') : '∞'} ${t("addNewBookForm.words")}`}
                                                input={
                                                    <NumberInput value={wordCount} setValue={setWordCount}
                                                                 placeholder={t("addNewBookForm.wordGoalPlaceholder")}/>
                                                }/>
                                    
                                    <InputField
                                        icon={faFileWord}
                                        fieldName={t("addNewBookForm.summary")}
                                        input={
                                            <TexteAreaInput
                                                value={summary}
                                                setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setSummary(e.target.value)}
                                                placeholder={t("addNewBookForm.summaryPlaceholder")}
                                            />
                                        }
                                    />
                                </>
                            )
                        }
                    </div>
                </div>
                
                <div
                    className="flex justify-between items-center p-5 border-t border-secondary/50 bg-secondary/20 rounded-b-2xl">
                    <div></div>
                    <div className="flex gap-3">
                        <CancelButton callBackFunction={() => setCloseForm(false)}/>
                        <SubmitButtonWLoading callBackAction={handleAddBook} isLoading={isAddingBook}
                                              text={t("addNewBookForm.add")}
                                              loadingText={t("addNewBookForm.adding")} icon={faBook}/>
                    </div>
                </div>
            </div>
            {bookTypeHint && <GuideTour stepId={0} steps={bookTypesHint} onClose={(): void => setBookTypeHint(false)}
                                        onComplete={async (): Promise<void> => setBookTypeHint(false)}/>}
        </div>
    );
}