'use client'
import {X} from 'lucide-react';
import IconButton from "@/components/ui/IconButton";
import React, {ChangeEvent, forwardRef, useContext, useImperativeHandle, useState} from "react";
import {apiDelete, apiPost} from "@/lib/api/client";
import axios, {AxiosResponse} from "axios";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
import {BookContext, BookContextProps} from "@/context/BookContext";
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
import TextInput from "@/components/form/TextInput";
import TextAreaInput from "@/components/form/TextAreaInput";
import InputField from "@/components/form/InputField";
import NumberInput from "@/components/form/NumberInput";
import DatePicker from "@/components/form/DatePicker";
import {configs, isDesktop} from "@/lib/configs";
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {useTranslations} from '@/lib/i18n';
import {LangContext, LangContextProps} from "@/context/LangContext";
import {BookProps} from "@/lib/types/book";
import {SettingRef} from "@/lib/types/settings";
import ImageDropZone from "@/components/form/ImageDropZone";
import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext";
import {SyncedBook} from "@/lib/types/synced-book";
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from "@/context/SyncQueueContext";

function BasicInformationSetting(_props: object, ref: React.ForwardedRef<SettingRef>): React.JSX.Element {
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {book, setBook}: BookContextProps = useContext<BookContextProps>(BookContext);
    const userToken: string = session?.accessToken ? session?.accessToken : '';
    const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);
    const {addToQueue}: LocalSyncQueueContextProps = useContext<LocalSyncQueueContextProps>(LocalSyncQueueContext);
    const {localSyncedBooks}: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext);
    const bookId: string = book?.bookId ? book?.bookId.toString() : '';
    
    const [currentImage, setCurrentImage] = useState<string>(book?.coverImage ?? '');
    const [title, setTitle] = useState<string>(book?.title ? book?.title : '');
    const [subTitle, setSubTitle] = useState<string>(book?.subTitle ? book?.subTitle : '');
    const [summary, setSummary] = useState<string>(book?.summary ? book?.summary : '');
    const [publicationDate, setPublicationDate] = useState<string>(book?.publicationDate ? book?.publicationDate : '');
    const [wordCount, setWordCount] = useState<number>(book?.desiredWordCount ? book?.desiredWordCount : 0);
    
    useImperativeHandle(ref, function (): SettingRef {
        return {
            handleSave: handleSave
        };
    });
    
    async function handleCoverImageChange(file: File): Promise<void> {
        const formData: FormData = new FormData();
        formData.append('bookId', bookId);
        formData.append('picture', file);
        
        try {
            const query: AxiosResponse<ArrayBuffer> = await axios({
                method: "POST",
                url: configs.apiUrl + `book/cover?bookid=${bookId}`,
                headers: {
                    'Authorization': `Bearer ${userToken}`,
                },
                params: {
                    lang: lang,
                    plateforme: 'web',
                },
                data: formData,
                responseType: 'arraybuffer'
            });
            
            const contentType: string = query.headers['content-type'] || 'image/jpeg';
            const blob: Blob = new Blob([query.data], {type: contentType});
            const reader: FileReader = new FileReader();
            
            reader.onloadend = function (): void {
                if (typeof reader.result === 'string') {
                    setCurrentImage(reader.result);
                }
            };
            
            reader.readAsDataURL(blob);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('basicInformationSetting.error.unknown'));
            }
        }
    }
    
    async function handleRemoveCurrentImage(): Promise<void> {
        try {
            const response: boolean = await apiDelete<boolean>(`book/cover/delete`, {
                bookId: bookId
            }, userToken, lang);
            if (!response) {
                errorMessage(t('basicInformationSetting.error.removeCover'));
            }
            setCurrentImage('');
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('basicInformationSetting.error.unknown'));
            }
        }
    }

    async function handleSave(): Promise<void> {
        if (!title) {
            errorMessage(t('basicInformationSetting.error.titleRequired'));
            return;
        }
        try {
            let response: boolean;
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                response = await tauri.updateBookBasicInfo({
                    bookId: bookId,
                    title: title,
                    subTitle: subTitle,
                    summary: summary,
                    publicationDate: publicationDate,
                    wordCount: wordCount,
                });
            } else {
                const basicInfoData = {
                    title, subTitle, summary, publicationDate, wordCount, bookId
                };
                response = await apiPost<boolean>('book/basic-information', basicInfoData, userToken, lang);

                if (isDesktop && localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === bookId)) {
                    addToQueue('update_book_basic_info', basicInfoData);
                }
            }
            if (!response) {
                errorMessage(t('basicInformationSetting.error.update'));
                return;
            }
            if (!book) {
                errorMessage(t('basicInformationSetting.error.unknown'));
                return;
            }
            const updatedBook: BookProps = {
                ...book,
                title: title,
                subTitle: subTitle,
                summary: summary,
                publicationDate: publicationDate,
                desiredWordCount: wordCount,
            };
            setBook(updatedBook);
            successMessage(t('basicInformationSetting.success.update'));
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('basicInformationSetting.error.unknown'));
            }
        }
    }

    return (
        <div className="space-y-6">
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                <InputField fieldName={t('basicInformationSetting.fields.title')} input={<TextInput
                    value={title}
                    setValue={(e: ChangeEvent<HTMLInputElement>): void => setTitle(e.target.value)}
                    placeholder={t('basicInformationSetting.fields.titlePlaceholder')}
                />}/>
                <InputField fieldName={t('basicInformationSetting.fields.subtitle')} input={<TextInput
                    value={subTitle}
                    setValue={(e: ChangeEvent<HTMLInputElement>): void => setSubTitle(e.target.value)}
                    placeholder={t('basicInformationSetting.fields.subtitlePlaceholder')}
                />}/>
            </div>
            
            <InputField fieldName={t('basicInformationSetting.fields.summary')} input={<TextAreaInput
                value={summary}
                setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setSummary(e.target.value)}
                placeholder={t('basicInformationSetting.fields.summaryPlaceholder')}
            />}/>
            
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                <InputField fieldName={t('basicInformationSetting.fields.publicationDate')} input={
                    <DatePicker
                        date={publicationDate}
                        setDate={(e: ChangeEvent<HTMLInputElement>): void => setPublicationDate(e.target.value)}
                    />
                }/>
                <InputField fieldName={t('basicInformationSetting.fields.wordCount')} input={
                    <NumberInput value={wordCount} setValue={setWordCount}
                                 placeholder={t('basicInformationSetting.fields.wordCountPlaceholder')}/>
                }/>
            </div>
            
            <div>
                {currentImage ? (
                    <div className="flex justify-center">
                        <div className="relative w-40">
                            <img src={currentImage} alt={t('basicInformationSetting.fields.coverImageAlt')}
                                 className="rounded-lg border border-secondary w-full h-auto"/>
                            <div className="absolute -top-2 -right-2">
                                <IconButton icon={X} variant="danger" size="sm"
                                            onClick={handleRemoveCurrentImage}/>
                            </div>
                        </div>
                    </div>
                ) : (
                    <ImageDropZone
                        onFileSelect={handleCoverImageChange}
                        label={t('basicInformationSetting.fields.coverImage')}
                    />
                )}
            </div>
        </div>
    );
}

export default forwardRef<SettingRef, object>(BasicInformationSetting);