'use client'

import React, {ChangeEvent, useContext, useEffect, useState} from 'react';
import {ArrowDown, ArrowUp, Bookmark, Trash2} from 'lucide-react';
import {ChapterListProps} from '@/lib/types/chapter';
import {apiDelete, apiPost} from '@/lib/api/client';
import {isDesktop} from '@/lib/configs';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext';
import {SyncedBook} from '@/lib/types/synced-book';
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from '@/context/SyncQueueContext';
import {BookContext, BookContextProps} from '@/context/BookContext';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import AlertBox from "@/components/ui/AlertBox";
import Collapse from "@/components/ui/Collapse";
import IconButton from "@/components/ui/IconButton";
import TextInput from "@/components/form/TextInput";
import OrderInput from "@/components/form/OrderInput";
import {useTranslations} from '@/lib/i18n';
import {LangContext, LangContextProps} from "@/context/LangContext";

interface MainChapterProps {
    chapters: ChapterListProps[];
    setChapters: React.Dispatch<React.SetStateAction<ChapterListProps[]>>;
}

export default function MainChapter({chapters, setChapters}: MainChapterProps) {
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext)
    const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    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 | undefined = book?.bookId;
    const token: string = session.accessToken;
    
    const [newChapterTitle, setNewChapterTitle] = useState<string>('');
    const [newChapterOrder, setNewChapterOrder] = useState<number>(0);
    
    const [deleteConfirmMessage, setDeleteConfirmMessage] = useState<boolean>(false);
    const [chapterIdToRemove, setChapterIdToRemove] = useState<string>('');
    
    function handleChapterTitleChange(chapterId: string, newTitle: string) {
        const updatedChapters: ChapterListProps[] = chapters.map((chapter: ChapterListProps): ChapterListProps => {
            if (chapter.chapterId === chapterId) {
                return {...chapter, title: newTitle};
            }
            return chapter;
        });
        setChapters(updatedChapters);
    }
    
    function moveChapter(index: number, direction: number): void {
        const visibleChapters: ChapterListProps[] = chapters
            .filter((chapter: ChapterListProps): boolean => chapter.chapterOrder !== -1)
            .sort((a: ChapterListProps, b: ChapterListProps): number => (a.chapterOrder || 0) - (b.chapterOrder || 0));
        
        const currentChapter: ChapterListProps = visibleChapters[index];
        const allChaptersIndex: number = chapters.findIndex(
            (chapter: ChapterListProps): boolean => chapter.chapterId === currentChapter.chapterId,
        );
        
        const updatedChapters: ChapterListProps[] = [...chapters];
        
        const currentOrder: number = updatedChapters[allChaptersIndex].chapterOrder || 0;
        const newOrder: number = Math.max(0, currentOrder + direction);
        
        updatedChapters[allChaptersIndex] = {
            ...updatedChapters[allChaptersIndex],
            chapterOrder: newOrder,
        };
        
        setChapters(updatedChapters);
    }
    
    function moveChapterUp(index: number): void {
        moveChapter(index, -1);
    }
    
    function moveChapterDown(index: number): void {
        moveChapter(index, 1);
    }
    
    async function deleteChapter(): Promise<void> {
        try {
            setDeleteConfirmMessage(false);
            let response: boolean;
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                response = await tauri.removeChapter(chapterIdToRemove, bookId ?? '', Date.now());
            } else {
                const deleteData = {bookId, chapterId: chapterIdToRemove};
                response = await apiDelete<boolean>('chapter/remove', deleteData, token, lang);

                if (isDesktop && bookId && localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === bookId)) {
                    addToQueue('remove_chapter', {...deleteData, deletedAt: Date.now()});
                }
            }
            if (!response) {
                errorMessage(t("mainChapter.errorDelete"));
            }
            const updatedChapters: ChapterListProps[] = chapters.filter((chapter: ChapterListProps): boolean => chapter.chapterId !== chapterIdToRemove,);
            setChapters(updatedChapters);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message)
            } else {
                errorMessage(t("mainChapter.errorUnknownDelete"));
            }
        }
    }
    
    async function addNewChapter(): Promise<void> {
        if (newChapterTitle.trim() === '') {
            return;
        }
        
        try {
            let responseId: string;
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                responseId = await tauri.addChapter({
                    bookId: bookId ?? '',
                    title: newChapterTitle,
                    chapterOrder: newChapterOrder ? newChapterOrder : 0,
                });
            } else {
                const addData = {bookId, wordsCount: 0, chapterOrder: newChapterOrder ? newChapterOrder : 0, title: newChapterTitle};
                responseId = await apiPost<string>('chapter/add', addData, token);

                if (isDesktop && bookId && localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === bookId)) {
                    addToQueue('add_chapter', addData);
                }
            }
            if (!responseId) {
                errorMessage(t("mainChapter.errorAdd"));
                return;
            }
            const newChapter: ChapterListProps = {
                chapterId: responseId,
                title: newChapterTitle,
                chapterOrder: newChapterOrder,
                summary: '',
                goal: '',
            };
            setChapters([...chapters, newChapter]);
            setNewChapterTitle('');
            
            setNewChapterOrder(newChapterOrder + 1);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message)
            } else {
                errorMessage(t("mainChapter.errorUnknownAdd"));
            }
        }
    }
    
    useEffect((): void => {
        const visibleChapters: ChapterListProps[] = chapters
            .filter((chapter: ChapterListProps): boolean => chapter.chapterOrder !== -1)
            .sort((a: ChapterListProps, b: ChapterListProps): number =>
                (a.chapterOrder || 0) - (b.chapterOrder || 0),
            );
        
        const nextOrder: number =
            visibleChapters.length > 0
                ? (visibleChapters[visibleChapters.length - 1].chapterOrder || 0) + 1
                : 0;
        
        setNewChapterOrder(nextOrder);
    }, [chapters]);
    
    const visibleChapters: ChapterListProps[] = chapters
        .filter((chapter: ChapterListProps): boolean => chapter.chapterOrder !== -1)
        .sort((a: ChapterListProps, b: ChapterListProps): number => (a.chapterOrder || 0) - (b.chapterOrder || 0));
    
    return (
        <div>
            <Collapse variant="card" icon={Bookmark} title={t("mainChapter.chapters")} children={
                <div className="space-y-4">
                    {visibleChapters.length > 0 ? (
                        <div className="space-y-2">
                            {visibleChapters.map((item: ChapterListProps, index: number) => (
                                <div key={item.chapterId} className="flex items-center gap-2">
                                    <span
                                        className="text-muted text-xs w-5 h-5 rounded-md bg-tertiary text-center leading-5 shrink-0">
                                        {item.chapterOrder !== undefined ? item.chapterOrder : index}
                                    </span>
                                    <div className="flex-1">
                                        <TextInput
                                            value={item.title}
                                            setValue={function (e: ChangeEvent<HTMLInputElement>): void {
                                                handleChapterTitleChange(item.chapterId, e.target.value);
                                            }}
                                            placeholder={t("mainChapter.chapterTitlePlaceholder")}
                                        />
                                    </div>
                                    <div className="flex shrink-0">
                                        <IconButton
                                            icon={ArrowUp}
                                            variant="ghost"
                                            size="sm"
                                            onClick={(): void => moveChapterUp(index)}
                                            disabled={item.chapterOrder === 0}
                                        />
                                        <IconButton
                                            icon={ArrowDown}
                                            variant="ghost"
                                            size="sm"
                                            onClick={(): void => moveChapterDown(index)}
                                        />
                                        <IconButton
                                            icon={Trash2}
                                            variant="danger"
                                            size="sm"
                                            onClick={(): void => {
                                                setChapterIdToRemove(item.chapterId);
                                                setDeleteConfirmMessage(true);
                                            }}
                                        />
                                    </div>
                                </div>
                            ))}
                        </div>
                    ) : (
                        <p className="text-text-secondary text-center py-2">
                            {t("mainChapter.noChapter")}
                        </p>
                    )}
                    
                    <div className="mt-3">
                        <OrderInput
                            value={newChapterTitle}
                            setValue={function (e: ChangeEvent<HTMLInputElement>): void {
                                setNewChapterTitle(e.target.value);
                            }}
                            order={newChapterOrder}
                            setOrder={setNewChapterOrder}
                            placeholder={t("mainChapter.newChapterPlaceholder")}
                            onAdd={addNewChapter}
                            isAddDisabled={newChapterTitle.trim() === ''}
                        />
                    </div>
                </div>
            }/>
            {
                deleteConfirmMessage &&
                <AlertBox title={t("mainChapter.deleteTitle")} message={t("mainChapter.deleteMessage")}
                          type={"danger"} onConfirm={deleteChapter}
                          onCancel={(): void => setDeleteConfirmMessage(false)}/>
            }
        </div>
    );
}