'use client';
import React, {ChangeEvent, Dispatch, SetStateAction, useContext, useState} from "react";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {isDesktop} from '@/lib/configs';
import {apiPost} from '@/lib/api/client';
import {createSeries} from '@/lib/tauri';
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
import {Book, Check, Layers, Pencil} from 'lucide-react';
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 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";

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

export default function AddNewSeriesForm({setCloseForm, onSeriesCreated}: AddNewSeriesFormProps) {
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {isCurrentlyOffline} = useContext(OfflineContext);
    const {
        serverSyncedBooks,
        setServerSyncedBooks,
        localSyncedBooks
    }: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext);
    const useLocal: boolean = isDesktop && isCurrentlyOffline();
    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 ?? '';
    
    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 useLocal: boolean = isDesktop && isCurrentlyOffline();
            const response: string = useLocal
                ? await createSeries({name, description: description || null, bookIds: selectedBookIds})
                : await apiPost<string>('series/add', {name, description: description || null, bookIds: selectedBookIds}, token, lang);
            if (!response) {
                errorMessage(t('addNewSeriesForm.error.addingSeries'));
                setIsAddingSeries(false);
                return;
            }
            successMessage(t('addNewSeriesForm.success'));
            
            if (selectedBookIds.length > 0) {
                setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] =>
                    prev.map((book: SyncedBook): SyncedBook =>
                        selectedBookIds.includes(book.id)
                            ? {...book, seriesId: response}
                            : book
                    )
                );
            } else {
                setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev]);
            }
            
            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 (
        <Modal
            icon={Layers}
            title={t("addNewSeriesForm.title")}
            onClose={(): void => setCloseForm(false)}
            size="md"
            footer={
                <>
                    <Button variant="secondary" onClick={() => setCloseForm(false)}>{t("common.cancel")}</Button>
                    <Button
                        variant="primary"
                        onClick={handleAddSeries}
                        isLoading={isAddingSeries}
                        loadingText={t("addNewSeriesForm.adding")}
                        icon={Layers}
                    >{t("addNewSeriesForm.add")}</Button>
                </>
            }
        >
            <InputField icon={Pencil} fieldName={t("addNewSeriesForm.name")} input={
                <TextInput
                    value={name}
                    setValue={(e: ChangeEvent<HTMLInputElement>): void => setName(e.target.value)}
                    placeholder={t("addNewSeriesForm.namePlaceholder")}
                />
            }/>
            
            <InputField
                icon={Pencil}
                fieldName={`${t("addNewSeriesForm.description")} (${t("addNewSeriesForm.optional")})`}
                input={
                    <TextAreaInput
                        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">
                    <Book className="w-4 h-4 text-primary" strokeWidth={1.75}/>
                    <span className="font-medium">{t("addNewSeriesForm.selectBooks")}</span>
                    {selectedBookIds.length > 0 && (
                        <span className="text-sm text-muted">
                            ({selectedBookIds.length} {t("addNewSeriesForm.selected")})
                        </span>
                    )}
                </div>
                
                {(useLocal ? localSyncedBooks : serverSyncedBooks).length === 0 ? (
                    <div className="text-center py-6 text-muted">
                        <Book className="w-8 h-8 mb-2 opacity-50" strokeWidth={1.75}/>
                        <p>{t("addNewSeriesForm.noBooks")}</p>
                    </div>
                ) : (
                    <div
                        className="max-h-48 overflow-y-auto rounded-xl border border-secondary bg-tertiary">
                        {(useLocal ? localSyncedBooks : serverSyncedBooks).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-colors duration-150 border-b border-secondary last:border-b-0 ${
                                        isSelected
                                            ? 'bg-secondary'
                                            : 'hover:bg-secondary/50'
                                    }`}
                                >
                                    <div
                                        className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${
                                            isSelected
                                                ? 'bg-primary/20 border-primary'
                                                : 'border-secondary'
                                        }`}>
                                        {isSelected && (
                                            <Check className="w-3 h-3 text-text-primary" strokeWidth={1.75}/>
                                        )}
                                    </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>
        </Modal>
    );
}
