'use client'
import React, {ChangeEvent, Dispatch, SetStateAction, useContext, useState} from "react";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
import {apiPost} from "@/lib/api/client";
import {isDesktop} from '@/lib/configs';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
import {Book, BookOpen, Calendar, FileText, Info, Pencil} from "lucide-react";
import SelectBox, {SelectBoxProps} from "@/components/form/SelectBox";
import {bookTypes} from "@/lib/constants/book";
import InputField from "@/components/form/InputField";
import TextInput from "@/components/form/TextInput";
import DatePicker from "@/components/form/DatePicker";
import NumberInput from "@/components/form/NumberInput";
import TextAreaInput from "@/components/form/TextAreaInput";
import Button from "@/components/ui/Button";
import Modal from "@/components/ui/Modal";
import GuideTour, {GuideStep} from "@/components/GuideTour";
import {useTranslations} from '@/lib/i18n';
import {LangContext, LangContextProps} from "@/context/LangContext";
import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext";
import {SyncedBook} from "@/lib/types/synced-book";

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

export default function AddNewBookForm({setCloseForm}: { setCloseForm: Dispatch<SetStateAction<boolean>> }) {
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {session, setSession}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {setServerSyncedBooks}: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext)
    const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);
    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 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 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 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 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 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>
        ),
    }]
    
    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 {
            let bookId: string;
            if (isDesktop && isCurrentlyOffline()) {
                bookId = await tauri.createBook({
                    title: title,
                    subTitle: subtitle,
                    type: selectedBookType,
                    summary: summary,
                    desiredReleaseDate: publicationDate,
                    desiredWordCount: wordCount,
                });
            } else {
                bookId = await apiPost<string>('book/add', {
                    title: title,
                    subTitle: subtitle,
                    type: selectedBookType,
                    summary: summary,
                    serie: 0,
                    publicationDate: publicationDate,
                    desiredWordCount: wordCount,
                }, token, lang);
            }
            if (!bookId) {
                errorMessage(t('addNewBookForm.error.addingBook'));
                setIsAddingBook(false);
                return;
            }
            const book: SyncedBook = {
                id: bookId,
                type: selectedBookType,
                title: title,
                subTitle: subtitle,
                seriesId: null,
                lastUpdate: new Date().getTime() / 1000,
                chapters: [],
                characters: [],
                locations: [],
                worlds: [],
                incidents: [],
                plotPoints: [],
                issues: [],
                actSummaries: [],
                guideLine: null,
                aiGuideLine: null
            };
            setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, 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 (
        <>
            <Modal
                icon={Book}
                title={t("addNewBookForm.title")}
                onClose={(): void => setCloseForm(false)}
                size="sm"
                footer={
                    <>
                        <Button variant="secondary" onClick={() => setCloseForm(false)}>{t("common.cancel")}</Button>
                        <Button
                            variant="primary"
                            onClick={handleAddBook}
                            isLoading={isAddingBook}
                            loadingText={t("addNewBookForm.adding")}
                            icon={Book}
                        >{t("addNewBookForm.add")}</Button>
                    </>
                }
            >
                <InputField icon={BookOpen} 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={Info}/>
                <InputField icon={Pencil} 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={Pencil} fieldName={t("addNewBookForm.subtitle")} input={
                            <TextInput value={subtitle}
                                       setValue={(e: ChangeEvent<HTMLInputElement>): void => setSubtitle(e.target.value)}
                                       placeholder={t("addNewBookForm.subtitlePlaceholder")}/>
                        }/>
                    )
                }
                
                <InputField icon={Calendar} fieldName={t("addNewBookForm.publicationDate")} input={
                    <DatePicker date={publicationDate}
                                setDate={(e: React.ChangeEvent<HTMLInputElement>): void => setPublicationDate(e.target.value)}/>
                }/>

                {
                    selectedBookType !== 'lyric' && (
                        <>
                            <InputField icon={FileText} 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={FileText}
                                fieldName={t("addNewBookForm.summary")}
                                input={
                                    <TextAreaInput
                                        value={summary}
                                        setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setSummary(e.target.value)}
                                        placeholder={t("addNewBookForm.summaryPlaceholder")}
                                    />
                                }
                            />
                        </>
                    )
                }
            </Modal>
            {bookTypeHint && <GuideTour stepId={0} steps={bookTypesHint} onClose={(): void => setBookTypeHint(false)}
                                        onComplete={async (): Promise<void> => setBookTypeHint(false)}/>}
        </>
    );
}