'use client'
import React, {ReactNode, useContext, useState} from 'react';
import {ArrowDown, ArrowUp} from 'lucide-react';
import {useTranslations} from '@/lib/i18n';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import {apiPost} from '@/lib/api/client';
import {isDesktop} from '@/lib/configs';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {BookContext, BookContextProps} from '@/context/BookContext';
import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext';
import {SyncedBook} from '@/lib/types/synced-book';
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from '@/context/SyncQueueContext';
import IconButton from '@/components/ui/IconButton';

export type SyncElementType = 'character' | 'world' | 'location' | 'spell';

interface SyncFieldWrapperProps {
    children: ReactNode;
    seriesElementId: string | null | undefined;
    seriesValue: string;
    currentValue: string;
    bookElementId: string;
    field: string;
    elementType: SyncElementType;
    onDownload: () => void;
    onSyncComplete?: () => void;
}

interface SeriesSyncUploadResponse {
    success: boolean;
    updatedCount: number;
}

export default function SyncFieldWrapper({
                                             children,
                                             seriesElementId,
                                             seriesValue,
                                             currentValue,
                                             bookElementId,
                                             field,
                                             elementType,
                                             onDownload,
                                             onSyncComplete
                                         }: SyncFieldWrapperProps) {
    const t = useTranslations();
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);
    const {addToQueue}: LocalSyncQueueContextProps = useContext<LocalSyncQueueContextProps>(LocalSyncQueueContext);
    const {localSyncedBooks}: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext);
    const {book}: BookContextProps = useContext<BookContextProps>(BookContext);

    const [isUploading, setIsUploading] = useState<boolean>(false);
    
    const isLinkedToSeries: boolean = !!seriesElementId;
    const hasSeriesDiff: boolean = isLinkedToSeries && seriesValue !== currentValue;
    
    async function handleUpload(): Promise<void> {
        if (!seriesElementId || isUploading) return;
        
        setIsUploading(true);
        try {
            const requestData = {type: elementType, bookElementId, field, value: currentValue};
            let response: SeriesSyncUploadResponse;

            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                response = await tauri.invoke<SeriesSyncUploadResponse>('series_sync_upload', {data: requestData});
            } else {
                response = await apiPost<SeriesSyncUploadResponse>('series/propagate', requestData, session.accessToken, lang);
                if (isDesktop && book?.bookId && localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === book.bookId)) {
                    addToQueue('series_sync_upload', requestData);
                }
            }
            if (response.success) {
                successMessage(t('syncField.uploadSuccess', {count: response.updatedCount}));
                if (onSyncComplete) {
                    onSyncComplete();
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        } finally {
            setIsUploading(false);
        }
    }
    
    function handleDownload(): void {
        onDownload();
    }
    
    if (!isLinkedToSeries) {
        return <>{children}</>;
    }
    
    return (
        <div className="flex items-center gap-2 w-full">
            <IconButton
                icon={ArrowDown}
                variant={hasSeriesDiff ? 'primary' : 'muted'}
                size="sm"
                onClick={handleDownload}
                disabled={!hasSeriesDiff}
                tooltip={t('syncField.downloadTooltip')}
            />

            <div className="flex-grow">
                {children}
            </div>
            
            <IconButton
                icon={ArrowUp}
                variant={hasSeriesDiff && !isUploading ? 'primary' : 'muted'}
                size="sm"
                onClick={handleUpload}
                disabled={isUploading || !hasSeriesDiff}
                tooltip={t('syncField.uploadTooltip')}
            />
        </div>
    );
}
