'use client';

import React, { useEffect, useState, useCallback } from 'react';
import { useLiveQuery } from 'dexie-react-hooks';
import { db, PendingScan, PendingTasting } from '@/lib/db';
import { scanLabel } from '@/app/actions/scanner';
import { enrichData } from '@/app/actions/enrich-data';
import { saveBottle } from '@/services/save-bottle';
import { saveTasting } from '@/services/save-tasting';

import { createClient } from '@/lib/supabase/client';
import { RefreshCw, CheckCircle2, AlertCircle, Loader2, Info, Send, X } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import TastingNoteForm from './TastingNoteForm';

// Helper to convert base64 to FormData
function base64ToFormData(base64: string, filename: string = 'image.webp'): FormData {
    const arr = base64.split(',');
    const mime = arr[0].match(/:(.*?);/)?.[1] || 'image/webp';
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    const file = new File([u8arr], filename, { type: mime });
    const formData = new FormData();
    formData.append('file', file);
    return formData;
}

export default function UploadQueue() {
    const supabase = createClient();
    const [isSyncing, setIsSyncing] = useState(false);
    const [currentProgress, setCurrentProgress] = useState<{ id: string, status: string } | null>(null);
    const [isCollapsed, setIsCollapsed] = useState(true);
    const [completedItems, setCompletedItems] = useState<{ id: string; name: string; bottleId?: string; type: 'scan' | 'tasting' }[]>([]);
    const [activeNoteScanId, setActiveNoteScanId] = useState<string | null>(null);

    const pendingScans = useLiveQuery(() => db.pending_scans.toArray(), [], [] as PendingScan[]);
    const pendingTastings = useLiveQuery(() => db.pending_tastings.toArray(), [], [] as PendingTasting[]);

    const totalInQueue = pendingScans.length + pendingTastings.length;

    const syncInProgress = React.useRef(false);

    const syncQueue = useCallback(async () => {
        if (syncInProgress.current || !navigator.onLine) return;

        syncInProgress.current = true;
        setIsSyncing(true);
        const { data: { user } } = await supabase.auth.getUser();

        if (!user) {
            console.error('No user found for background sync');
            setIsSyncing(false);
            return;
        }

        try {
            // 1. Sync Scans (Magic Shots) - Two-Step Flow
            // We use a transaction to "claim" items currently not being synced by another tab/instance
            const scansToSync = await db.transaction('rw', db.pending_scans, async () => {
                const all = await db.pending_scans.toArray();
                const now = Date.now();
                const available = all.filter(i => {
                    if (i.syncing) return false;
                    // Exponential backoff: don't retry immediately if it failed before
                    if (i.attempts && i.attempts > 0) {
                        const backoff = Math.min(Math.pow(2, i.attempts) * 1000, 30000); // Max 30s
                        const lastAttempt = i.timestamp; // We use timestamp for simplicity or add last_attempt
                        // For now we trust timestamp + backoff if timestamp is updated on fail
                        return (now - i.timestamp) > backoff;
                    }
                    return true;
                });
                for (const item of available) {
                    await db.pending_scans.update(item.id!, { syncing: 1 });
                }
                return available;
            });

            for (const item of scansToSync) {
                const itemId = `scan-${item.id}`;
                setCurrentProgress({ id: itemId, status: 'OCR Analyse...' });
                try {
                    let bottleData;

                    // Check if this is an offline scan with pre-filled metadata
                    // CRITICAL: If name is empty, it's placeholder metadata and needs OCR enrichment
                    if (item.metadata && item.metadata.name && item.metadata.name.trim().length > 0) {
                        console.log('[UploadQueue] Valid offline metadata found - skipping OCR');
                        bottleData = item.metadata;
                        setCurrentProgress({ id: itemId, status: 'Speichere Offline-Scan...' });
                    } else {
                        console.log('[UploadQueue] No valid metadata - running OCR analysis');
                        // Normal online scan - perform AI analysis
                        // Step 1: Fast OCR
                        const formData = base64ToFormData(item.imageBase64);
                        const ocrResult = await scanLabel(formData);

                        if (ocrResult.success && ocrResult.data) {
                            bottleData = ocrResult.data;

                            // Step 2: Background enrichment (before saving)
                            if (bottleData.is_whisky && bottleData.name && bottleData.distillery) {
                                setCurrentProgress({ id: itemId, status: 'Enrichment...' });
                                const enrichResult = await enrichData(
                                    bottleData.name,
                                    bottleData.distillery,
                                    undefined,
                                    item.locale
                                );

                                if (enrichResult.success && enrichResult.data) {
                                    // Merge enrichment data into bottle data
                                    bottleData = {
                                        ...bottleData,
                                        suggested_tags: enrichResult.data.suggested_tags,
                                        suggested_custom_tags: enrichResult.data.suggested_custom_tags
                                    };
                                }
                            }
                        } else {
                            throw new Error(ocrResult.error || 'Analyse fehlgeschlagen');
                        }
                    }

                    // Step 3: Save bottle with all data
                    setCurrentProgress({ id: itemId, status: 'Speichere Flasche...' });
                    const save = await saveBottle(bottleData, item.imageBase64, user.id);

                    if (save.success && save.data) {
                        const newBottleId = save.data.id;

                        // Reconcile pending tastings linked to this temp_id
                        if (item.temp_id) {
                            const linkedTastings = await db.pending_tastings
                                .where('pending_bottle_id')
                                .equals(item.temp_id)
                                .toArray();

                            for (const lt of linkedTastings) {
                                await db.pending_tastings.update(lt.id!, {
                                    bottle_id: newBottleId,
                                    pending_bottle_id: undefined
                                });
                            }
                        }

                        setCompletedItems(prev => [...prev.slice(-4), {
                            id: itemId,
                            name: bottleData.name || 'Unbekannter Whisky',
                            bottleId: newBottleId,
                            type: 'scan'
                        }]);
                        await db.pending_scans.delete(item.id!);
                    }
                } catch (err) {
                    const errorMessage = err instanceof Error ? err.message : 'Unbekannter Fehler';
                    console.error('Scan sync failed:', err);
                    setCurrentProgress({ id: itemId, status: `Fehler: ${errorMessage.substring(0, 20)}...` });
                    // Unmark as syncing on failure, update attempts and timestamp for backoff
                    await db.pending_scans.update(item.id!, {
                        syncing: 0,
                        attempts: (item.attempts || 0) + 1,
                        last_error: errorMessage,
                        timestamp: Date.now() // Update timestamp to use for backoff
                    });
                    await new Promise(r => setTimeout(r, 1000));
                }
            }

            // 2. Sync Tastings
            const tastingsToSync = await db.transaction('rw', db.pending_tastings, async () => {
                const all = await db.pending_tastings.toArray();
                const now = Date.now();
                const available = all.filter(i => {
                    if (i.syncing || i.pending_bottle_id) return false;
                    // Exponential backoff
                    if (i.attempts && i.attempts > 0) {
                        const backoff = Math.min(Math.pow(2, i.attempts) * 1000, 30000);
                        return (now - new Date(i.tasted_at).getTime()) > backoff;
                    }
                    return true;
                });
                for (const item of available) {
                    await db.pending_tastings.update(item.id!, { syncing: 1 });
                }
                return available;
            });

            for (const item of tastingsToSync) {
                const itemId = `tasting-${item.id}`;
                setCurrentProgress({ id: itemId, status: 'Synchronisiere Tasting...' });
                try {
                    const result = await saveTasting({
                        ...item.data,
                        is_sample: item.data.is_sample ?? false,
                        bottle_id: item.bottle_id as string,
                        tasted_at: item.tasted_at
                    });
                    if (result.success) {
                        setCompletedItems(prev => [...prev.slice(-4), {
                            id: itemId,
                            name: 'Tasting Note',
                            bottleId: item.bottle_id,
                            type: 'tasting'
                        }]);
                        await db.pending_tastings.delete(item.id!);
                    } else {
                        throw new Error(result.error);
                    }
                } catch (err) {
                    const errorMessage = err instanceof Error ? err.message : 'Unbekannter Fehler';
                    console.error('Tasting sync failed:', err);
                    setCurrentProgress({ id: itemId, status: `Fehler: ${errorMessage.substring(0, 20)}...` });
                    await db.pending_tastings.update(item.id!, {
                        syncing: 0,
                        attempts: (item.attempts || 0) + 1,
                        last_error: errorMessage
                        // Note: we use tasted_at or add a last_attempt for backoff. 
                        // For now let's just use the tried attempts as a counter and a fixed wait.
                    });
                    await new Promise(r => setTimeout(r, 1000));
                }
            }
        } catch (err) {
            console.error('Global Sync Error:', err);
        } finally {
            syncInProgress.current = false;
            setIsSyncing(false);
            setCurrentProgress(null);

            // Dispatch event to notify that sync is complete and collection should be refreshed
            window.dispatchEvent(new CustomEvent('collection-updated'));
        }
    }, [supabase]); // Removed pendingScans, pendingTastings, totalInQueue, isSyncing

    useEffect(() => {
        const handleOnline = () => {
            console.log('Online! Syncing in 2s...');
            setTimeout(syncQueue, 2000);
        };

        window.addEventListener('online', handleOnline);

        // Initial check: only trigger if online and items exist, 
        // and we aren't already syncing.
        if (navigator.onLine && totalInQueue > 0 && !isSyncing) {
            // we use a small timeout to debounce background sync
            const timer = setTimeout(syncQueue, 3000);
            return () => {
                window.removeEventListener('online', handleOnline);
                clearTimeout(timer);
            };
        }

        return () => window.removeEventListener('online', handleOnline);
        // Trigger when the presence of items changes or online status
    }, [syncQueue, totalInQueue > 0]); // Removed isSyncing to break the loop

    // Clear stale syncing flags on mount
    useEffect(() => {
        const clearStaleFlags = async () => {
            await db.transaction('rw', [db.pending_scans, db.pending_tastings], async () => {
                await db.pending_scans.where('syncing').equals(1).modify({ syncing: 0 });
                await db.pending_tastings.where('syncing').equals(1).modify({ syncing: 0 });
            });
        };
        clearStaleFlags();
    }, []);

    if (totalInQueue === 0) return null;

    return (
        <div className="fixed bottom-24 right-6 md:bottom-6 md:right-6 z-[100] flex flex-col items-end gap-3 translate-y-0">
            <AnimatePresence mode="wait">
                {!isCollapsed ? (
                    <motion.div
                        key="expanded"
                        initial={{ opacity: 0, scale: 0.9, y: 20 }}
                        animate={{ opacity: 1, scale: 1, y: 0 }}
                        exit={{ opacity: 0, scale: 0.9, y: 20 }}
                        className="w-[calc(100vw-3rem)] md:w-96 bg-zinc-900 border border-white/10 rounded-[2.5rem] shadow-2xl overflow-hidden"
                    >
                        {/* Header */}
                        <div
                            className="p-5 bg-zinc-800/50 flex items-center justify-between cursor-pointer"
                            onClick={() => setIsCollapsed(true)}
                        >
                            <div className="flex items-center gap-3">
                                <div className="relative">
                                    <RefreshCw size={18} className={isSyncing ? 'animate-spin text-orange-500' : 'text-zinc-500'} />
                                    {totalInQueue > 0 && !isSyncing && (
                                        <div className="absolute -top-1 -right-1 w-2 h-2 bg-orange-500 rounded-full animate-pulse" />
                                    )}
                                </div>
                                <div className="flex flex-col">
                                    <span className="text-[10px] font-black uppercase tracking-[0.2em] text-zinc-400">Sync status</span>
                                    <span className="text-xs font-bold text-white">
                                        {isSyncing ? 'Synchronisiere...' : navigator.onLine ? 'Warten auf Upload' : 'Offline'}
                                    </span>
                                </div>
                            </div>
                            <div className="flex items-center gap-2">
                                <span className="bg-orange-600 text-[10px] font-black px-2.5 py-1 rounded-full text-white shadow-lg shadow-orange-950/40">
                                    {totalInQueue}
                                </span>
                                <X size={16} className="text-zinc-500" />
                            </div>
                        </div>

                        {/* Content */}
                        <div className="p-5 space-y-4 max-h-[60vh] md:max-h-[400px] overflow-y-auto custom-scrollbar">
                            <div className="space-y-3">
                                {/* Completed Items */}
                                {completedItems.length > 0 && (
                                    <div className="space-y-2 pb-2 border-b border-white/5">
                                        <div className="flex items-center gap-2 text-[9px] font-black uppercase tracking-[0.2em] text-green-500 mb-2">
                                            <CheckCircle2 size={10} />
                                            Fertig
                                        </div>
                                        {completedItems.map((item) => (
                                            <div key={`done-${item.id}`} className="flex items-center justify-between p-2.5 rounded-2xl bg-green-500/10 border border-green-500/20">
                                                <div className="flex flex-col gap-0.5 min-w-0">
                                                    <span className="text-[10px] font-black text-green-500 uppercase tracking-widest">
                                                        {item.type === 'scan' ? 'Scan bereit' : 'Tasting bereit'}
                                                    </span>
                                                    <span className="text-[11px] font-bold text-white truncate pr-2">
                                                        {item.name}
                                                    </span>
                                                </div>
                                                {item.bottleId && (
                                                    <a
                                                        href={`/bottles/${item.bottleId}`}
                                                        className="shrink-0 px-3 py-1.5 bg-green-500 hover:bg-green-600 text-white text-[10px] font-black uppercase rounded-lg transition-all"
                                                    >
                                                        Details
                                                    </a>
                                                )}
                                            </div>
                                        ))}
                                    </div>
                                )}

                                {/* Scans */}
                                {pendingScans.map((item) => (
                                    <div key={`scan-${item.id}`} className="flex flex-col gap-2.5 p-3 rounded-2xl bg-white/5 border border-white/5">
                                        <div className="flex items-center justify-between">
                                            <div className="flex items-center gap-3">
                                                <div className="w-10 h-10 rounded-xl bg-zinc-800 overflow-hidden ring-1 ring-white/10 shrink-0">
                                                    <img src={item.imageBase64} className="w-full h-full object-cover opacity-60" />
                                                </div>
                                                <div className="flex flex-col gap-0.5">
                                                    <span className="text-[10px] font-black text-orange-500/80 uppercase tracking-widest">Flaschen-Scan</span>
                                                    <span className="text-[11px] font-medium text-zinc-300">
                                                        {currentProgress?.id === `scan-${item.id}` ? (
                                                            <span className="flex items-center gap-1.5">
                                                                <Loader2 size={10} className="animate-spin" />
                                                                {currentProgress.status}
                                                            </span>
                                                        ) : 'In Warteschlange...'}
                                                    </span>
                                                </div>
                                            </div>
                                        </div>

                                        <button
                                            onClick={() => setActiveNoteScanId(activeNoteScanId === item.temp_id ? null : item.temp_id)}
                                            className="w-full py-2.5 bg-orange-600/10 hover:bg-orange-600/20 text-orange-500 text-[10px] font-black uppercase rounded-xl transition-all flex items-center justify-center gap-2 border border-orange-500/10"
                                        >
                                            <Send size={12} />
                                            {activeNoteScanId === item.temp_id ? 'Abbrechen' : 'Notiz hinzufügen'}
                                        </button>

                                        {activeNoteScanId === item.temp_id && (
                                            <div className="mt-2">
                                                <TastingNoteForm
                                                    pendingBottleId={item.temp_id}
                                                    onSuccess={() => setActiveNoteScanId(null)}
                                                />
                                            </div>
                                        )}
                                    </div>
                                ))}

                                {/* Tastings */}
                                {pendingTastings.map((item) => (
                                    <div key={`tasting-${item.id}`} className="flex items-center justify-between p-3 rounded-2xl bg-white/5 border border-white/5">
                                        <div className="flex items-center gap-3">
                                            <div className="w-10 h-10 rounded-xl bg-orange-900/20 flex items-center justify-center ring-1 ring-orange-500/20 shrink-0">
                                                <div className="text-xs font-black text-orange-500">{item.data.rating}</div>
                                            </div>
                                            <div className="flex flex-col gap-0.5">
                                                <span className="text-[10px] font-black text-orange-500/80 uppercase tracking-widest">Tasting Note</span>
                                                <span className="text-[11px] font-medium text-zinc-300 line-clamp-1">
                                                    {item.pending_bottle_id ? 'Wartet auf Scan...' : currentProgress?.id === `tasting-${item.id}` ? currentProgress.status : 'Wartet auf Sync...'}
                                                </span>
                                            </div>
                                        </div>
                                    </div>
                                ))}
                            </div>

                            {navigator.onLine && !isSyncing && (
                                <button
                                    onClick={() => syncQueue()}
                                    className="w-full py-3.5 bg-white/5 hover:bg-white/10 text-orange-500 text-[10px] font-black uppercase rounded-2xl transition-all border border-white/5 flex items-center justify-center gap-2"
                                >
                                    <RefreshCw size={14} />
                                    Sync jetzt
                                </button>
                            )}
                        </div>
                    </motion.div>
                ) : (
                    <motion.button
                        key="bubble"
                        initial={{ opacity: 0, scale: 0.5, y: 20 }}
                        animate={{ opacity: 1, scale: 1, y: 0 }}
                        exit={{ opacity: 0, scale: 0.5, y: 20 }}
                        onClick={() => setIsCollapsed(false)}
                        className="relative w-14 h-14 bg-zinc-900 border border-white/10 rounded-full shadow-2xl flex items-center justify-center text-white hover:bg-zinc-800 transition-all group"
                    >
                        <RefreshCw size={20} className={isSyncing ? 'animate-spin text-orange-500' : 'text-zinc-500 group-hover:text-white transition-colors'} />
                        <div className="absolute -top-1 -right-1 bg-orange-600 text-[9px] font-black w-5 h-5 rounded-full flex items-center justify-center shadow-lg shadow-orange-950/40 ring-2 ring-zinc-900">
                            {totalInQueue}
                        </div>
                        {isSyncing && (
                            <div className="absolute inset-0 rounded-full border-2 border-orange-500/50 border-t-transparent animate-spin" />
                        )}
                    </motion.button>
                )}
            </AnimatePresence>
        </div>
    );
}

