'use client'
import {fetch} from "@tauri-apps/plugin-http";
import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react';
import {Check} from 'lucide-react';
import Button from '@/components/ui/Button';
import PulseLoader from '@/components/ui/PulseLoader';
import {useTranslations} from '@/lib/i18n';
import {BookContext, BookContextProps} from '@/context/BookContext';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import {configs, isDesktop} from '@/lib/configs';
import {apiGet} from '@/lib/api/client';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import {ChapterExportInfo, ChapterExportSelection, ExportFormat,} from '@/lib/types/chapter';
import {chapterVersions} from '@/lib/constants/chapter';
import {SelectBoxProps} from '@/components/form/SelectBox';

const formats: ExportFormat[] = ['epub', 'pdf', 'docx'];

const formatExtensions: Record<ExportFormat, string> = {
    epub: '.epub',
    pdf: '.pdf',
    docx: '.docx',
};

export default function ExportSetting(): React.JSX.Element {
    const t = useTranslations();
    const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {successMessage, errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);

    const [selectedFormat, setSelectedFormat] = useState<ExportFormat>('epub');
    const [chaptersExportInfo, setChaptersExportInfo] = useState<ChapterExportInfo[]>([]);
    const [chapterSelections, setChapterSelections] = useState<ChapterExportSelection[]>([]);
    const [isLoadingChapters, setIsLoadingChapters] = useState<boolean>(true);
    const [isExporting, setIsExporting] = useState<boolean>(false);
    
    const selectedCount: number = useMemo(
        () => chapterSelections.filter((selection: ChapterExportSelection): boolean => selection.selected).length,
        [chapterSelections],
    );
    
    const allSelected: boolean = useMemo(
        () => chapterSelections.length > 0 && chapterSelections.every((selection: ChapterExportSelection): boolean => selection.selected),
        [chapterSelections],
    );
    
    const canExport: boolean = useMemo(
        () => !isExporting && selectedCount > 0,
        [isExporting, selectedCount],
    );
    
    const fetchChaptersExportInfo = useCallback(async (): Promise<void> => {
        if (!book?.bookId) {
            setIsLoadingChapters(false);
            return;
        }
        setIsLoadingChapters(true);
        try {
            let data: ChapterExportInfo[];
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                data = await tauri.getBookExportInfo(book.bookId) as ChapterExportInfo[];
            } else {
                data = await apiGet<ChapterExportInfo[]>(
                    'book/chapters/export-info', session.accessToken, lang, {id: book.bookId}
                );
            }
            
            setChaptersExportInfo(data);
            setChapterSelections(
                data.map((chapter: ChapterExportInfo): ChapterExportSelection => ({
                    chapterId: chapter.chapterId,
                    version: chapter.availableVersions.length > 0
                        ? chapter.availableVersions[chapter.availableVersions.length - 1]
                        : 1,
                    selected: true,
                })),
            );
        } catch {
            errorMessage(t('exportOption.serverError'));
        } finally {
            setIsLoadingChapters(false);
        }
    }, [book?.bookId, session.accessToken, lang, errorMessage, t]);
    
    useEffect((): void => {
        fetchChaptersExportInfo();
    }, [fetchChaptersExportInfo]);
    
    function toggleChapterSelection(chapterId: string): void {
        setChapterSelections((previous: ChapterExportSelection[]): ChapterExportSelection[] =>
            previous.map((selection: ChapterExportSelection): ChapterExportSelection =>
                selection.chapterId === chapterId
                    ? {...selection, selected: !selection.selected}
                    : selection,
            ),
        );
    }
    
    function toggleAllChapters(): void {
        const newSelected: boolean = !allSelected;
        setChapterSelections((previous: ChapterExportSelection[]): ChapterExportSelection[] =>
            previous.map((selection: ChapterExportSelection): ChapterExportSelection => ({
                ...selection,
                selected: newSelected,
            })),
        );
    }
    
    function setChapterVersion(chapterId: string, version: number): void {
        setChapterSelections((previous: ChapterExportSelection[]): ChapterExportSelection[] =>
            previous.map((selection: ChapterExportSelection): ChapterExportSelection =>
                selection.chapterId === chapterId
                    ? {...selection, version}
                    : selection,
            ),
        );
    }
    
    function getVersionLabel(version: number): string {
        const match: SelectBoxProps | undefined = chapterVersions.find(
            (chapterVersion: SelectBoxProps): boolean => chapterVersion.value === String(version),
        );
        return match ? t(match.label) : `V${version}`;
    }
    
    async function handleExport(): Promise<void> {
        if (!book?.bookId) {
            errorMessage(t('exportOption.noBookSelected'));
            return;
        }
        if (selectedCount === 0) {
            errorMessage(t('exportOption.noChaptersSelected'));
            return;
        }
        
        setIsExporting(true);
        
        const selectedChapters: { chapterId: string; version: number }[] = chapterSelections
            .filter((selection: ChapterExportSelection): boolean => selection.selected)
            .map((selection: ChapterExportSelection): { chapterId: string; version: number } => ({
                chapterId: selection.chapterId,
                version: selection.version,
            }));
        
        try {
            const response: Response = await fetch(`${configs.apiUrl}book/export`, {
                method: 'POST',
                headers: {
                    Authorization: `Bearer ${session.accessToken}`,
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    bookId: book.bookId,
                    format: selectedFormat,
                    chapters: selectedChapters,
                }),
            });
            
            if (!response.ok) {
                errorMessage(t('exportOption.downloadError'));
                return;
            }
            
            const blob: Blob = await response.blob();
            const bookName: string = book.subTitle ? `${book.title} - ${book.subTitle}` : book.title;
            const fileName: string = `${bookName}${formatExtensions[selectedFormat]}`;
            
            const virtualUrl: string = window.URL.createObjectURL(blob);
            const downloadLink: HTMLAnchorElement = document.createElement('a');
            downloadLink.href = virtualUrl;
            downloadLink.download = fileName;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            downloadLink.remove();
            window.URL.revokeObjectURL(virtualUrl);
            
            successMessage(t('exportOption.downloadSuccess', {format: selectedFormat.toUpperCase()}));
        } catch {
            errorMessage(t('exportOption.unknownError'));
        } finally {
            setIsExporting(false);
        }
    }
    
    return (
        <div className="p-4 space-y-6">
            <div>
                <h3 className="text-sm font-semibold text-text-primary mb-3">
                    {t('exportOption.formatLabel')}
                </h3>
                <div className="flex gap-3">
                    {formats.map((format: ExportFormat) => (
                        <Button
                            key={format}
                            variant={selectedFormat === format ? 'primary' : 'secondary'}
                            size="sm"
                            onClick={(): void => setSelectedFormat(format)}
                        >
                            {format.toUpperCase()}
                        </Button>
                    ))}
                </div>
            </div>
            
            <div>
                <h3 className="text-sm font-semibold text-text-primary mb-3">
                    {t('exportOption.chapters')}
                </h3>
                
                {isLoadingChapters ? (
                    <PulseLoader text={t('exportOption.loadingChapters')} size="sm"/>
                ) : chaptersExportInfo.length === 0 ? (
                    <p className="text-text-secondary text-sm text-center py-8">
                        {t('exportOption.noChaptersAvailable')}
                    </p>
                ) : (
                    <>
                        <div className="mb-3">
                            <Button variant="ghost" size="sm" onClick={toggleAllChapters}>
                                {allSelected ? t('exportOption.deselectAll') : t('exportOption.selectAll')}
                            </Button>
                        </div>

                        <div className="space-y-1">
                            {chaptersExportInfo.map((chapter: ChapterExportInfo, index: number) => {
                                const selection: ChapterExportSelection = chapterSelections[index];
                                return (
                                    <div key={chapter.chapterId} className="border-b border-secondary pb-2">
                                        <button
                                            onClick={(): void => toggleChapterSelection(chapter.chapterId)}
                                            className="flex items-center gap-3 w-full py-2 text-left hover:bg-tertiary rounded-lg px-2 transition-all"
                                        >
                                            <div
                                                className={`w-5 h-5 rounded flex items-center justify-center border transition-colors ${
                                                selection.selected
                                                    ? 'bg-primary/20 border-primary'
                                                    : 'border-secondary bg-tertiary'
                                            }`}>
                                                {selection.selected && (
                                                    <Check className="w-3 h-3 text-text-primary" strokeWidth={1.75}/>
                                                )}
                                            </div>
                                            <span className={`text-sm font-medium truncate ${
                                                selection.selected ? 'text-text-primary' : 'text-text-secondary'
                                            }`}>
                                                {chapter.chapterOrder !== -1 ? `${chapter.chapterOrder}. ` : ''}
                                                {chapter.title}
                                            </span>
                                        </button>
                                        
                                        {selection.selected && chapter.availableVersions.length > 1 && (
                                            <div className="flex flex-wrap gap-2 ml-10 mt-1 mb-1">
                                                {chapter.availableVersions.map((version: number) => (
                                                    <button
                                                        key={version}
                                                        onClick={(): void => setChapterVersion(chapter.chapterId, version)}
                                                        className={`px-3 py-1 rounded-full text-xs font-medium transition-all border ${
                                                            selection.version === version
                                                                ? 'bg-primary/20 text-primary border-primary/50'
                                                                : 'bg-tertiary text-text-secondary border-secondary hover:bg-secondary'
                                                        }`}
                                                    >
                                                        {getVersionLabel(version)}
                                                    </button>
                                                ))}
                                            </div>
                                        )}
                                    </div>
                                );
                            })}
                        </div>
                    </>
                )}
            </div>
            
            <Button variant="primary" size="lg" onClick={handleExport} disabled={!canExport}
                    isLoading={isExporting} loadingText={t('exportOption.exporting')}
                    fullWidth>
                {t('exportOption.exportButton')} {selectedFormat.toUpperCase()}
                {selectedCount > 0 ? ` (${selectedCount})` : ''}
            </Button>
        </div>
    );
}
