import {ChapterListProps, ChapterProps} from "@/lib/models/Chapter";
import React, {useContext, useEffect, useRef, useState} from "react";
import System from "@/lib/models/System";
import {BookContext} from "@/context/BookContext";
import {AlertContext} from "@/context/AlertContext";
import {ChapterContext} from "@/context/ChapterContext";
import {SessionContext} from "@/context/SessionContext";
import {faSheetPlastic} from "@fortawesome/free-solid-svg-icons";
import ListItem from "@/components/ListItem";
import AlertBox from "@/components/AlertBox";
import {useTranslations} from "next-intl";
import InlineAddInput from "@/components/form/InlineAddInput";
import {LangContext} from "@/context/LangContext";

export default function ScribeChapterComponent() {
    const t = useTranslations();
    const {lang} = useContext(LangContext)

    const {book} = useContext(BookContext);
    const {chapter, setChapter} = useContext(ChapterContext);
    const {errorMessage, successMessage} = useContext(AlertContext);
    const {session} = useContext(SessionContext);
    const userToken: string = session?.accessToken ? session?.accessToken : '';
    
    const [chapters, setChapters] = useState<ChapterListProps[]>([])
    
    const [newChapterName, setNewChapterName] = useState<string>('');
    const [newChapterOrder, setNewChapterOrder] = useState<number>(1);

    const [deleteConfirmationMessage, setDeleteConfirmationMessage] = useState<boolean>(false);
    const [removeChapterId, setRemoveChapterId] = useState<string>('');
    
    const chapterRefs = useRef<Map<string, HTMLDivElement>>(new Map());
    const scrollContainerRef = useRef<HTMLUListElement>(null);
    
    useEffect((): void => {
        getChapterList().then();
    }, [book]);
    
    useEffect((): void => {
        setNewChapterOrder(getNextChapterOrder());
    }, [chapters]);
    
    useEffect((): void => {
        if (chapter?.chapterId && scrollContainerRef.current) {
            // Small delay to ensure DOM is ready
            setTimeout(() => {
                const element = chapterRefs.current.get(chapter.chapterId);
                const container = scrollContainerRef.current;
                
                if (element && container) {
                    const containerRect = container.getBoundingClientRect();
                    const elementRect = element.getBoundingClientRect();
                    
                    // Calculate relative position
                    const relativeTop = elementRect.top - containerRect.top + container.scrollTop;
                    const scrollPosition = relativeTop - (containerRect.height / 2) + (elementRect.height / 2);
                    
                    container.scrollTo({
                        top: Math.max(0, scrollPosition),
                        behavior: 'smooth'
                    });
                }
            }, 100);
        }
    }, [chapter?.chapterId]);
    
    function getNextChapterOrder(): number {
        const maxOrder: number = Math.max(0, ...chapters.map((chap: ChapterListProps) => chap.chapterOrder ?? 0));
        return maxOrder + 1;
    }
    
    async function getChapterList(): Promise<void> {
        try {
            const response: ChapterListProps[] = await System.authGetQueryToServer<ChapterListProps[]>(`book/chapters?id=${book?.bookId}`, userToken, lang);
            if (response) {
                setChapters(response);
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("scribeChapterComponent.errorFetchChapters"));
            }
        }
    }
    
    async function getChapter(chapterId: string): Promise<void> {
        const version: number = chapter?.chapterContent.version ? chapter?.chapterContent.version : 2;
        try {
            const response: ChapterProps = await System.authGetQueryToServer<ChapterProps>(`chapter/whole`, userToken, lang, {
                bookid: book?.bookId,
                id: chapterId,
                version: version,
            });
            if (!response) {
                errorMessage(t("scribeChapterComponent.errorFetchChapter"));
                return;
            }
            setChapter(response);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("scribeChapterComponent.errorFetchChapter"));
            }
        }
    }
    
    async function handleChapterUpdate(chapterId: string, title: string, chapterOrder: number): Promise<void> {
        try {
            const response: boolean = await System.authPostToServer<boolean>('chapter/update', {
                chapterId: chapterId,
                chapterOrder: chapterOrder,
                title: title,
            }, userToken, lang);
            if (!response) {
                errorMessage(t("scribeChapterComponent.errorChapterUpdate"));
                return;
            }
            successMessage(t("scribeChapterComponent.successUpdate"));
            setChapters((prevState: ChapterListProps[]): ChapterListProps[] => {
                return prevState.map((chapter: ChapterListProps): ChapterListProps => {
                    if (chapter.chapterId === chapterId) {
                        chapter.chapterOrder = chapterOrder;
                        chapter.title = title;
                    }
                    return chapter;
                });
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(t("scribeChapterComponent.errorChapterUpdateFr"));
            } else {
                errorMessage(t("scribeChapterComponent.errorChapterUpdateEn"));
            }
        }
    }
    
    async function handleDeleteConfirmation(chapterId: string): Promise<void> {
        setDeleteConfirmationMessage(true);
        setRemoveChapterId(chapterId);
    }
    
    async function handleDeleteChapter(): Promise<void> {
        try {
            setDeleteConfirmationMessage(false);
            const response: boolean = await System.authDeleteToServer<boolean>('chapter/remove', {
                bookId: book?.bookId,
                chapterId: removeChapterId,
            }, userToken, lang);
            if (!response) {
                errorMessage(t("scribeChapterComponent.errorChapterDelete"));
                return;
            }
            const updatedChapters: ChapterListProps[] = chapters.filter(
                (chapter: ChapterListProps): boolean => chapter.chapterId !== removeChapterId,
            );
            setChapters(updatedChapters);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("scribeChapterComponent.unknownErrorChapterDelete"));
            }
        }
    }
    
    async function handleAddChapter(chapterOrder: number): Promise<void> {
        if (!newChapterName && chapterOrder >= 0) {
            errorMessage(t("scribeChapterComponent.errorChapterNameRequired"));
            return;
        }
        const chapterTitle: string = chapterOrder >= 0 ? newChapterName : book?.title as string;
        try {
            const chapterId: string = await System.authPostToServer<string>('chapter/add', {
                bookId: book?.bookId,
                chapterOrder: chapterOrder,
                title: chapterTitle
            }, userToken, lang);
            if (!chapterId) {
                errorMessage(t("scribeChapterComponent.errorChapterSubmit", {chapterName: newChapterName}));
                return;
            }
            const newChapter: ChapterListProps = {
                chapterId: chapterId,
                title: chapterTitle,
                chapterOrder: chapterOrder
            }
            setChapters((prevState: ChapterListProps[]): ChapterListProps[] => {
                return [newChapter, ...prevState]
            })
            await getChapter(chapterId);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("scribeChapterComponent.errorChapterSubmit", {chapterName: newChapterName}));
            }
        }
    }
    
    return (
        <div className="flex-1 flex flex-col p-4 min-h-0">
            <div className="mb-4">
                <div className="flex items-center gap-2 mb-3">
                    <div className="h-6 w-1 bg-primary rounded-full"></div>
                    <h3 className="text-lg font-bold text-primary tracking-wide">{t("scribeChapterComponent.sheetHeading")}</h3>
                </div>
                <ul className="space-y-2">
                    {
                        chapters.filter((chap: ChapterListProps): boolean => {
                                return chap.chapterOrder !== undefined && chap.chapterOrder < 0;
                            })
                            .sort((a: ChapterListProps, b: ChapterListProps): number => {
                                const aOrder: number = a.chapterOrder ?? 0;
                                const bOrder: number = b.chapterOrder ?? 0;
                                return aOrder - bOrder;
                            }).map((chap: ChapterListProps) => (
                            <div key={chap.chapterId}
                                 ref={(el): void => {
                                     if (el) {
                                         chapterRefs.current.set(chap.chapterId, el);
                                     } else {
                                         chapterRefs.current.delete(chap.chapterId);
                                     }
                                 }}>
                                <ListItem icon={faSheetPlastic}
                                          onClick={(): Promise<void> => getChapter(chap.chapterId)}
                                          selectedId={chapter?.chapterId ?? ''}
                                          id={chap.chapterId}
                                          text={chap.title}/>
                            </div>
                        ))
                    }
                    {
                        chapters.filter((chap: ChapterListProps): boolean => {
                            return chap.chapterOrder !== undefined && chap.chapterOrder < 0;
                        }).length === 0 &&
                        <li onClick={(): Promise<void> => handleAddChapter(-1)}
                            className="group p-3 bg-secondary/30 rounded-xl hover:bg-secondary cursor-pointer transition-all hover:shadow-md border border-secondary/30 hover:border-primary/30">
                            <span
                                className="text-sm font-medium text-muted group-hover:text-text-primary transition-colors">
                                {t("scribeChapterComponent.createSheet")}
                            </span>
                        </li>
                    }
                </ul>
            </div>
            
            <div className="flex-1 flex flex-col mt-6 min-h-0">
                <div className="flex items-center gap-2 mb-3">
                    <div className="h-6 w-1 bg-primary rounded-full"></div>
                    <h3 className="text-lg font-bold text-primary tracking-wide">{t("scribeChapterComponent.chaptersHeading")}</h3>
                </div>
                <ul ref={scrollContainerRef} className="flex-1 space-y-2 overflow-y-auto pr-2 min-h-0">
                    {
                        chapters.filter((chap: ChapterListProps): boolean => {
                                return !(chap.chapterOrder && chap.chapterOrder < 0);
                            })
                            .sort((a: ChapterListProps, b: ChapterListProps): number => {
                                const aOrder: number = a.chapterOrder ?? 0;
                                const bOrder: number = b.chapterOrder ?? 0;
                                return aOrder - bOrder;
                            }).map((chap: ChapterListProps) => (
                            <div key={chap.chapterId}
                                 ref={(el): void => {
                                     if (el) {
                                         chapterRefs.current.set(chap.chapterId, el);
                                     } else {
                                         chapterRefs.current.delete(chap.chapterId);
                                     }
                                 }}>
                                <ListItem onClick={(): Promise<void> => getChapter(chap.chapterId)}
                                          isEditable={true}
                                          handleUpdate={handleChapterUpdate}
                                          handleDelete={handleDeleteConfirmation}
                                          selectedId={chapter?.chapterId ?? ''}
                                          id={chap.chapterId} text={chap.title}
                                          numericalIdentifier={chap.chapterOrder}/>
                            </div>
                        ))
                    }
                </ul>
                <div className="mt-2 shrink-0">
                    <InlineAddInput
                        value={newChapterName}
                        setValue={setNewChapterName}
                        numericalValue={newChapterOrder}
                        setNumericalValue={setNewChapterOrder}
                        placeholder={t("scribeChapterComponent.addChapterPlaceholder")}
                        onAdd={async (): Promise<void> => {
                            await handleAddChapter(newChapterOrder);
                            setNewChapterName("");
                        }}
                        showNumericalInput={true}
                    />
                </div>
            </div>
            {
                deleteConfirmationMessage &&
                <AlertBox title={t("scribeChapterComponent.deleteChapterTitle")}
                          message={t("scribeChapterComponent.deleteChapterMessage")}
                          type={"danger"} onConfirm={(): Promise<void> => handleDeleteChapter()}
                          onCancel={(): void => setDeleteConfirmationMessage(false)}/>
            }
        </div>
    )
}