'use client'
import React, {ChangeEvent, Dispatch, SetStateAction, useContext, useRef, useState} from "react";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
import {apiPost, apiUpload} from "@/lib/api/client";
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
import {Book, BookOpen, FileInput, FileText, Layers, Pencil, Square, SquareCheck} from 'lucide-react';
import SelectBox, {SelectBoxProps} from "@/components/form/SelectBox";
import {bookTypes} from "@/lib/constants/book";
import {chapterVersions} from "@/lib/constants/chapter";
import {ImportChapterSelection, ImportConfirmBody, ParsedChapterPreview, ParsedDocxResponse} from "@/lib/types/import";
import InputField from "@/components/form/InputField";
import TextInput from "@/components/form/TextInput";
import TextAreaInput from "@/components/form/TextAreaInput";
import Button from "@/components/ui/Button";
import Badge from "@/components/ui/Badge";
import Modal from "@/components/ui/Modal";
import {useTranslations} from '@/lib/i18n';
import {LangContext, LangContextProps} from "@/context/LangContext";
import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext";
import {SyncedBook} from "@/lib/types/synced-book";

const docxAccept: string = '.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document';

export default function ImportBookForm({setCloseForm}: { setCloseForm: Dispatch<SetStateAction<boolean>> }) {
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {setServerSyncedBooks}: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext);
    const fileInputRef: React.RefObject<HTMLInputElement | null> = useRef<HTMLInputElement>(null);
    
    const [isParsing, setIsParsing] = useState<boolean>(false);
    const [isImporting, setIsImporting] = useState<boolean>(false);
    const [importId, setImportId] = useState<string>('');
    const [chapters, setChapters] = useState<ImportChapterSelection[]>([]);
    const [title, setTitle] = useState<string>('');
    const [subTitle, setSubTitle] = useState<string>('');
    const [summary, setSummary] = useState<string>('');
    const [selectedBookType, setSelectedBookType] = useState<string>('short');
    const [selectedVersion, setSelectedVersion] = useState<string>('2');
    
    const token: string = session?.accessToken ?? '';
    const hasParsedFile: boolean = importId.length > 0 && chapters.length > 0;
    const selectedCount: number = chapters.filter((chapter: ImportChapterSelection): boolean => chapter.selected).length;
    
    async function handleFileChange(event: ChangeEvent<HTMLInputElement>): Promise<void> {
        const file: File | undefined = event.target.files?.[0];
        if (!file) return;
        
        if (!file.name.endsWith('.docx')) {
            errorMessage(t('importBook.error.invalidFormat'));
            return;
        }
        
        setIsParsing(true);
        setImportId('');
        setChapters([]);
        
        try {
            const response: ParsedDocxResponse = await apiUpload<ParsedDocxResponse>(
                'book/import/parse',
                file,
                token,
                lang
            );
            
            setImportId(response.importId);
            setChapters(
                response.chapters.map((chapter: ParsedChapterPreview): ImportChapterSelection => ({
                    index: chapter.index,
                    title: chapter.title,
                    wordCount: chapter.wordCount,
                    selected: true,
                }))
            );
        } catch (parseError: unknown) {
            if (parseError instanceof Error) {
                errorMessage(parseError.message);
            } else {
                errorMessage(t('importBook.error.parseFailed'));
            }
        } finally {
            setIsParsing(false);
        }
    }
    
    function toggleChapter(chapterIndex: number): void {
        setChapters((previousChapters: ImportChapterSelection[]): ImportChapterSelection[] =>
            previousChapters.map((chapter: ImportChapterSelection): ImportChapterSelection =>
                chapter.index === chapterIndex ? {...chapter, selected: !chapter.selected} : chapter
            )
        );
    }
    
    function toggleAllChapters(selectAll: boolean): void {
        setChapters((previousChapters: ImportChapterSelection[]): ImportChapterSelection[] =>
            previousChapters.map((chapter: ImportChapterSelection): ImportChapterSelection => ({
                ...chapter,
                selected: selectAll,
            }))
        );
    }
    
    async function handleImport(): Promise<void> {
        if (!title.trim()) {
            errorMessage(t('importBook.error.titleRequired'));
            return;
        }
        if (!selectedBookType) {
            errorMessage(t('importBook.error.typeRequired'));
            return;
        }
        if (selectedCount === 0) {
            errorMessage(t('importBook.error.noChaptersSelected'));
            return;
        }
        
        setIsImporting(true);
        try {
            const selectedChapterIndexes: number[] = chapters
                .filter((chapter: ImportChapterSelection): boolean => chapter.selected)
                .map((chapter: ImportChapterSelection): number => chapter.index);
            
            const importBody: ImportConfirmBody = {
                importId,
                title: title.trim(),
                subTitle: subTitle.trim(),
                summary: summary.trim(),
                type: selectedBookType,
                version: parseInt(selectedVersion, 10),
                selectedChapterIndexes,
            };
            
            const importResponse: { bookId: string } = await apiPost<{ bookId: string }>(
                'book/import',
                importBody,
                token,
                lang
            );
            
            const newBook: SyncedBook = {
                id: importResponse.bookId,
                type: selectedBookType,
                title: title.trim(),
                subTitle: subTitle.trim() || null,
                seriesId: null,
                lastUpdate: new Date().getTime() / 1000,
                chapters: [],
                characters: [],
                locations: [],
                worlds: [],
                incidents: [],
                plotPoints: [],
                issues: [],
                actSummaries: [],
                guideLine: null,
                aiGuideLine: null,
            };
            setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, newBook]);
            
            successMessage(t('importBook.success'));
            setCloseForm(false);
        } catch (importError: unknown) {
            if (importError instanceof Error) {
                errorMessage(importError.message);
            } else {
                errorMessage(t('importBook.error.importFailed'));
            }
        } finally {
            setIsImporting(false);
        }
    }
    
    return (
        <Modal
            icon={FileInput}
            title={t("importBook.header")}
            onClose={(): void => setCloseForm(false)}
            size="sm"
            footer={hasParsedFile ? (
                <>
                    <Button variant="secondary" onClick={() => setCloseForm(false)}>{t("common.cancel")}</Button>
                    <Button
                        variant="primary"
                        onClick={handleImport}
                        isLoading={isImporting}
                        loadingText={t("importBook.importing")}
                        icon={FileInput}
                    >{t("importBook.submit")}</Button>
                </>
            ) : undefined}
        >
            <input
                ref={fileInputRef}
                type="file"
                accept={docxAccept}
                onChange={handleFileChange}
                className="hidden"
            />
            <Button
                variant="dashed"
                size="lg"
                icon={isParsing ? undefined : FileText}
                isLoading={isParsing}
                loadingText={t('importBook.parsing')}
                onClick={(): void => fileInputRef.current?.click()}
                disabled={isParsing}
                fullWidth
            >
                {t('importBook.pickFile')}
            </Button>
            
            {hasParsedFile && (
                <>
                    <InputField icon={BookOpen} fieldName={t("importBook.fields.type")} input={
                        <SelectBox
                            onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => setSelectedBookType(e.target.value)}
                            data={bookTypes.map((types: SelectBoxProps): SelectBoxProps => ({
                                value: types.value,
                                label: t(types.label)
                            }))}
                            defaultValue={selectedBookType}
                            placeholder={t("addNewBookForm.typePlaceholder")}
                        />
                    }/>
                    
                    <InputField icon={Pencil} fieldName={t("importBook.fields.title")} input={
                        <TextInput
                            value={title}
                            setValue={(e: ChangeEvent<HTMLInputElement>): void => setTitle(e.target.value)}
                            placeholder={t("addNewBookForm.bookTitlePlaceholder")}
                        />
                    }/>
                    
                    <InputField icon={Pencil} fieldName={t("importBook.fields.subTitle")} input={
                        <TextInput
                            value={subTitle}
                            setValue={(e: ChangeEvent<HTMLInputElement>): void => setSubTitle(e.target.value)}
                            placeholder={t("addNewBookForm.subtitlePlaceholder")}
                        />
                    }/>
                    
                    <InputField icon={Book} fieldName={t("importBook.fields.summary")} input={
                        <TextAreaInput
                            value={summary}
                            setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setSummary(e.target.value)}
                            placeholder={t("addNewBookForm.summaryPlaceholder")}
                        />
                    }/>
                    
                    <InputField icon={Layers} fieldName={t("importBook.fields.version")} input={
                        <SelectBox
                            onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => setSelectedVersion(e.target.value)}
                            data={chapterVersions.map((version: SelectBoxProps): SelectBoxProps => ({
                                value: version.value,
                                label: t(version.label)
                            }))}
                            defaultValue={selectedVersion}
                            placeholder={""}
                        />
                    }/>
                    
                    <div className="mt-2">
                        <div className="flex justify-between items-center mb-3">
                            <h3 className="text-text-primary text-xl font-['ADLaM_Display'] font-medium flex items-center gap-2">
                                <BookOpen className="text-primary w-5 h-5" strokeWidth={1.75}/>
                                {t('importBook.chapters.title')}
                            </h3>
                            <Badge variant="muted" size="sm">
                                {t('importBook.chapters.detected', {count: chapters.length})}
                            </Badge>
                        </div>
                        
                        <div className="mb-3 hover:underline w-fit">
                            <Button variant="ghost" size="sm"
                                    onClick={(): void => toggleAllChapters(selectedCount < chapters.length)}>
                                {selectedCount === chapters.length
                                    ? t('importBook.chapters.deselectAll')
                                    : t('importBook.chapters.selectAll')}
                            </Button>
                        </div>
                        
                        <div className="space-y-1">
                            {chapters.map((chapter: ImportChapterSelection) => (
                                <button
                                    key={chapter.index}
                                    onClick={(): void => toggleChapter(chapter.index)}
                                    className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg hover:bg-secondary transition-all duration-150"
                                >
                                    {chapter.selected
                                        ? <SquareCheck className="w-4 h-4 text-primary" strokeWidth={1.75}/>
                                        : <Square className="w-4 h-4 text-muted" strokeWidth={1.75}/>
                                    }
                                    <div className="flex-1 text-left">
                                        <span
                                            className={`text-sm font-medium block truncate ${chapter.selected ? 'text-text-primary' : 'text-muted'}`}>
                                            {chapter.title}
                                        </span>
                                        <span className="text-xs text-muted">
                                            {chapter.wordCount.toLocaleString('fr-FR')} {t('importBook.chapters.words')}
                                        </span>
                                    </div>
                                </button>
                            ))}
                        </div>
                    </div>
                </>
            )}
        </Modal>
    );
}
