'use client'
import React, {ReactNode, useContext, useState} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faArrowDown, faArrowUp, faSpinner} from '@fortawesome/free-solid-svg-icons';
import {useTranslations} from 'next-intl';
import {SessionContext} from '@/context/SessionContext';
import {AlertContext} from '@/context/AlertContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from '@/context/SyncQueueContext';
import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext';
import {BookContext} from '@/context/BookContext';
import {SyncedBook} from '@/lib/models/SyncedBook';
import System from '@/lib/models/System';
import * as tauri from '@/lib/tauri';

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} = useContext(SessionContext);
    const {errorMessage, successMessage} = useContext(AlertContext);
    const {lang} = useContext<LangContextProps>(LangContext);
    const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
    const {addToQueue} = useContext<LocalSyncQueueContextProps>(LocalSyncQueueContext);
    const {localSyncedBooks} = useContext<BooksSyncContextProps>(BooksSyncContext);
    const {book} = useContext(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: bookElementId,
                field: field,
                value: currentValue
            };

            let response: SeriesSyncUploadResponse;

            if (isCurrentlyOffline() || book?.localBook) {
                response = await tauri.seriesSyncUpload(requestData) as SeriesSyncUploadResponse;
            } else {
                response = await System.authPostToServer<SeriesSyncUploadResponse>(
                    'series/propagate',
                    requestData,
                    session.accessToken,
                    lang
                );

                if (book?.bookId && localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === book.bookId)) {
                    addToQueue('series_sync_upload', {data: 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-start gap-2 w-full">
            <button
                onClick={handleDownload}
                disabled={!hasSeriesDiff}
                title={t('syncField.downloadTooltip')}
                className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center transition-all duration-200 ${
                    hasSeriesDiff
                        ? 'bg-blue-500/20 text-blue-400 hover:bg-blue-500/40 hover:scale-110 cursor-pointer'
                        : 'bg-secondary/30 text-muted cursor-not-allowed opacity-50'
                }`}
            >
                <FontAwesomeIcon icon={faArrowDown} className="w-3.5 h-3.5"/>
            </button>

            <div className="flex-grow">
                {children}
            </div>

            <button
                onClick={handleUpload}
                disabled={isUploading || !hasSeriesDiff}
                title={t('syncField.uploadTooltip')}
                className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center transition-all duration-200 ${
                    hasSeriesDiff && !isUploading
                        ? 'bg-primary/20 text-primary hover:bg-primary/40 hover:scale-110 cursor-pointer'
                        : 'bg-secondary/30 text-muted cursor-not-allowed opacity-50'
                }`}
            >
                {isUploading ? (
                    <FontAwesomeIcon icon={faSpinner} className="w-3.5 h-3.5 animate-spin"/>
                ) : (
                    <FontAwesomeIcon icon={faArrowUp} className="w-3.5 h-3.5"/>
                )}
            </button>
        </div>
    );
}
