'use client';
import React, {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, faCheck, faLayerGroup, faPencilAlt, faX} from "@fortawesome/free-solid-svg-icons";
import InputField from "@/components/form/InputField";
import TextInput from "@/components/form/TextInput";
import TexteAreaInput from "@/components/form/TexteAreaInput";
import CancelButton from "@/components/form/CancelButton";
import SubmitButtonWLoading from "@/components/form/SubmitButtonWLoading";
import {useTranslations} from "next-intl";
import {LangContext, LangContextProps} from "@/context/LangContext";
import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext";
import {SyncedBook} from "@/lib/models/SyncedBook";
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";
import {SeriesSyncContext, SeriesSyncContextProps} from "@/context/SeriesSyncContext";
import {SyncedSeries, SyncedSeriesBook} from "@/lib/models/SyncedSeries";

interface AddNewSeriesFormProps {
    setCloseForm: Dispatch<SetStateAction<boolean>>;
    onSeriesCreated?: (seriesId: string, name: string) => void;
}

export default function AddNewSeriesForm({setCloseForm, onSeriesCreated}: AddNewSeriesFormProps) {
    const t = useTranslations();
    const {lang} = useContext<LangContextProps>(LangContext);
    const {session} = useContext(SessionContext);
    const {errorMessage, successMessage} = useContext(AlertContext);
    const {serverSyncedBooks, setServerSyncedBooks, localSyncedBooks, setLocalSyncedBooks} = useContext<BooksSyncContextProps>(BooksSyncContext);
    const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
    const {serverSyncedSeries, localSyncedSeries} = useContext<SeriesSyncContextProps>(SeriesSyncContext);

    // Get all bookIds already in a series
    const booksAlreadyInSeries: Set<string> = new Set(
        (isCurrentlyOffline() ? localSyncedSeries : serverSyncedSeries)
            .flatMap((series: SyncedSeries): string[] =>
                series.books.map((book: SyncedSeriesBook): string => book.bookId)
            )
    );
    const modalRef: React.RefObject<HTMLDivElement | null> = useRef<HTMLDivElement>(null);

    const [name, setName] = useState<string>('');
    const [description, setDescription] = useState<string>('');
    const [selectedBookIds, setSelectedBookIds] = useState<string[]>([]);
    const [isAddingSeries, setIsAddingSeries] = useState<boolean>(false);

    const token: string = session?.accessToken ?? '';

    useEffect((): () => void => {
        document.body.style.overflow = 'hidden';
        return (): void => {
            document.body.style.overflow = 'auto';
        };
    }, []);

    function toggleBookSelection(bookId: string): void {
        setSelectedBookIds((prev: string[]): string[] => {
            if (prev.includes(bookId)) {
                return prev.filter((id: string): boolean => id !== bookId);
            }
            return [...prev, bookId];
        });
    }

    async function handleAddSeries(): Promise<void> {
        if (!name) {
            errorMessage(t('addNewSeriesForm.error.nameMissing'));
            return;
        }
        if (name.length < 2) {
            errorMessage(t('addNewSeriesForm.error.nameTooShort'));
            return;
        }
        if (name.length > 100) {
            errorMessage(t('addNewSeriesForm.error.nameTooLong'));
            return;
        }

        setIsAddingSeries(true);
        try {
            const createData = {
                name: name,
                description: description || null,
                bookIds: selectedBookIds,
            };
            let response: string;

            if (isCurrentlyOffline()) {
                response = await window.electron.invoke<string>('db:series:create', createData);
            } else {
                response = await System.authPostToServer<string>(
                    'series/add',
                    createData,
                    token,
                    lang
                );
            }

            if (!response) {
                errorMessage(t('addNewSeriesForm.error.addingSeries'));
                setIsAddingSeries(false);
                return;
            }
            successMessage(t('addNewSeriesForm.success'));

            if (selectedBookIds.length > 0) {
                if (isCurrentlyOffline()) {
                    setLocalSyncedBooks((prev: SyncedBook[]): SyncedBook[] =>
                        prev.map((book: SyncedBook): SyncedBook =>
                            selectedBookIds.includes(book.id)
                                ? {...book, seriesId: response}
                                : book
                        )
                    );
                } else {
                    setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] =>
                        prev.map((book: SyncedBook): SyncedBook =>
                            selectedBookIds.includes(book.id)
                                ? {...book, seriesId: response}
                                : book
                        )
                    );
                }
            }

            if (onSeriesCreated) {
                onSeriesCreated(response, name);
            }
            setIsAddingSeries(false);
            setCloseForm(false);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('addNewSeriesForm.error.addingSeries'));
            }
            setIsAddingSeries(false);
        }
    }

    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-2/5 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={faLayerGroup} className="w-6 h-6"/>
                        {t("addNewSeriesForm.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={faPencilAlt} fieldName={t("addNewSeriesForm.name")} input={
                            <TextInput
                                value={name}
                                setValue={(e: ChangeEvent<HTMLInputElement>): void => setName(e.target.value)}
                                placeholder={t("addNewSeriesForm.namePlaceholder")}
                            />
                        }/>

                        <InputField
                            icon={faPencilAlt}
                            fieldName={`${t("addNewSeriesForm.description")} (${t("addNewSeriesForm.optional")})`}
                            input={
                                <TexteAreaInput
                                    value={description}
                                    setValue={(e: ChangeEvent<HTMLTextAreaElement>): void => setDescription(e.target.value)}
                                    placeholder={t("addNewSeriesForm.descriptionPlaceholder")}
                                />
                            }
                        />

                        <div className="space-y-3">
                            <div className="flex items-center gap-2 text-text-primary">
                                <FontAwesomeIcon icon={faBook} className="w-4 h-4 text-primary"/>
                                <span className="font-medium">{t("addNewSeriesForm.selectBooks")}</span>
                                {selectedBookIds.length > 0 && (
                                    <span className="text-sm text-muted">
                                        ({selectedBookIds.length} {t("addNewSeriesForm.selected")})
                                    </span>
                                )}
                            </div>

                            {(isCurrentlyOffline() ? localSyncedBooks : serverSyncedBooks)
                                .filter((book: SyncedBook): boolean => !booksAlreadyInSeries.has(book.id)).length === 0 ? (
                                <div className="text-center py-6 text-muted">
                                    <FontAwesomeIcon icon={faBook} className="w-8 h-8 mb-2 opacity-50"/>
                                    <p>{t("addNewSeriesForm.noBooks")}</p>
                                </div>
                            ) : (
                                <div className="max-h-48 overflow-y-auto rounded-xl border border-secondary/50 bg-secondary/20">
                                    {(isCurrentlyOffline() ? localSyncedBooks : serverSyncedBooks)
                                        .filter((book: SyncedBook): boolean => !booksAlreadyInSeries.has(book.id))
                                        .map((book: SyncedBook) => {
                                        const isSelected: boolean = selectedBookIds.includes(book.id);
                                        return (
                                            <button
                                                key={book.id}
                                                type="button"
                                                onClick={(): void => toggleBookSelection(book.id)}
                                                className={`w-full flex items-center gap-3 px-4 py-3 transition-all duration-200 border-b border-secondary/30 last:border-b-0 ${
                                                    isSelected
                                                        ? 'bg-primary/20 hover:bg-primary/30'
                                                        : 'hover:bg-secondary/50'
                                                }`}
                                            >
                                                <div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-all ${
                                                    isSelected
                                                        ? 'bg-primary border-primary'
                                                        : 'border-secondary/50'
                                                }`}>
                                                    {isSelected && (
                                                        <FontAwesomeIcon icon={faCheck} className="w-3 h-3 text-white"/>
                                                    )}
                                                </div>
                                                <div className="flex-1 text-left">
                                                    <div className="text-text-primary font-medium">{book.title}</div>
                                                    {book.subTitle && (
                                                        <div className="text-sm text-muted">{book.subTitle}</div>
                                                    )}
                                                </div>
                                            </button>
                                        );
                                    })}
                                </div>
                            )}
                        </div>
                    </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={handleAddSeries}
                            isLoading={isAddingSeries}
                            text={t("addNewSeriesForm.add")}
                            loadingText={t("addNewSeriesForm.adding")}
                            icon={faLayerGroup}
                        />
                    </div>
                </div>
            </div>
        </div>
    );
}
