'use client';

import { useState, useEffect, useCallback } from 'react';
import { db, Item } from '@/lib/db';
import { inventoryApi } from '@/lib/api';
import { fetchAndCacheItems, syncOfflineOperations } from '@/lib/sync';
import { useScanner } from '@/hooks/useScanner';
import { useStockAdjustment } from '@/hooks/useStockAdjustment';
import { useSync } from '@/hooks/useSync';
import Scanner from '@/components/Scanner';
import AIOnboarding from '@/components/AIOnboarding';
import PageShell from '@/components/PageShell';
import ItemComparisonModal from '@/components/ItemComparisonModal';
import StockAdjustmentPanel from '@/components/StockAdjustmentPanel';
import NewItemDialog from '@/components/NewItemDialog';
import ScannerSection from '@/components/ScannerSection';
import SearchModal from '@/components/inventory/SearchModal';
import { toast } from 'react-hot-toast';
import {
  Package,
  Camera,
  Plus,
  Minus,
  Trash2,
  AlertTriangle,
  X,
  ChevronRight,
  Edit2,
  RefreshCw,
  Search
} from 'lucide-react';
import { generateBarcode128, getQRCodeURL } from '@/lib/labels';
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
import axios from 'axios';
import versionData from '../VERSION.json';

interface User {
  id: number;
  username: string;
  role: string;
}

function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export default function Home() {
  const [mounted, setMounted] = useState(false);
  const [isOnline, setIsOnline] = useState(true);
  const [inventory, setInventory] = useState<Item[]>([]);
  const [showOnboarding, setShowOnboarding] = useState(false);
  const [selectedBoxLabel, setSelectedBoxLabel] = useState<string | null>(null);
  const [selectedItem, setSelectedItem] = useState<Item | null>(null);
  const [boxMatches, setBoxMatches] = useState<Item[]>([]);
  const [isEditing, setIsEditing] = useState(false);
  const [editedItem, setEditedItem] = useState<Partial<Item>>({});
  const [trashReason, setTrashReason] = useState('Damaged');
  const [currentUser, setCurrentUser] = useState<any | null>(null);
  const [categories, setCategories] = useState<any[]>([]);
  const [comparisonModal, setComparisonModal] = useState<{ show: boolean, newItem: any, existingItem: any, existingId: number | null }>({ show: false, newItem: null, existingItem: null, existingId: null });
  const [comparisonLoading, setComparisonLoading] = useState(false);
  const [showSearch, setShowSearch] = useState(false);

  const { syncing, handleSync } = useSync({
    isOnline,
    currentUser,
    onInventoryUpdate: setInventory
  });

  const {
    mode,
    setMode,
    showScanner,
    setShowScanner,
    lastScanned,
    isScannerReady,
    fieldScanning,
    setFieldScanning,
    onScanSuccess,
    onOCRMatch,
  } = useScanner({
    inventory,
    isOnline,
    onSync: handleSync,
    onMatchFound: (item, adjustType) => {
      setSelectedItem(item);
      setAdjustType(adjustType);
    },
    onMultipleMatches: (items) => {
      setBoxMatches(items);
    },
    onFieldCapture: (field, value) => {
      if (field === 'box_label') {
        setEditedItem(prev => ({ ...prev, box_label: value }));
      }
    }
  });

  const {
    adjustQty,
    setAdjustQty,
    adjustType,
    setAdjustType,
    handleAdjustStock
  } = useStockAdjustment({
    selectedItem,
    isOnline,
    currentUser,
    onAdjustmentComplete: () => {
      setSelectedItem(null);
    },
    onInventoryUpdate: setInventory
  });

  useEffect(() => {
    if (!localStorage.getItem('inventory_token')) {
      window.location.href = '/login';
      return;
    }
    
    setMounted(true);
    setIsOnline(navigator.onLine);

    const savedUser = localStorage.getItem('inventory_user');
    if (savedUser) {
      setCurrentUser(JSON.parse(savedUser));
    }

    // Initial data fetch
    inventoryApi.getCategories().then(c => setCategories(c)).catch(() => { });
    loadInventory();

    const handleOnline = () => {
      setIsOnline(true);
    };
    const handleOffline = () => setIsOnline(false);

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);

    // Active polling for network status AND periodic background refresh (30s)
    const interval = setInterval(() => {
      setIsOnline(navigator.onLine);
      if (navigator.onLine) {
        loadInventory(); // Keep other devices in sync
      }
    }, 30000);

    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
      clearInterval(interval);
    };
  }, []);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
        e.preventDefault();
        setShowSearch(!showSearch);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [showSearch]);

  const loadInventory = async () => {
    const cached = await db.items.toArray();
    setInventory(cached);

    if (navigator.onLine) {
      const fresh = await fetchAndCacheItems();
      setInventory(fresh);
    }
  };

  const handleOnboardingComplete = async (itemData: any) => {
    try {
      if (itemData.part_number) {
        itemData.part_number = itemData.part_number.toLowerCase();
      }

      // Prepare data for backend: convert Blob to base64 and rename fields
      const backendData = { ...itemData };
      delete backendData.extractedImageBlob; // Remove Blob from local DB version

      // If extracted image blob is present, convert to base64 for backend
      if (itemData.extractedImageBlob) {
        const reader = new FileReader();
        reader.readAsDataURL(itemData.extractedImageBlob);

        await new Promise((resolve, reject) => {
          reader.onload = () => {
            const base64 = (reader.result as string).split(',')[1]; // Remove data URL prefix
            backendData.extracted_image_bytes = base64;
            backendData.image_processing = itemData.imageProcessing; // Use correct field name for API
            delete backendData.imageProcessing; // Remove old field name
            resolve(null);
          };
          reader.onerror = reject;
        });
      }

      // 1. Add to local DB cache (without Blob)
      await db.items.add(itemData);

      // 2. If online, try to push to backend immediately
      if (isOnline && currentUser) {
        try {
          await inventoryApi.createItem(currentUser.id, backendData);
          toast.success("Item saved to cloud catalog!");
          setShowOnboarding(false);
          await loadInventory();
        } catch (err: any) {
          const status = err.response?.status;
          const responseData = err.response?.data;

          if (status === 409 && responseData?.detail) {
            // Show comparison modal for duplicate part number
            const detail = responseData.detail;
            setComparisonModal({
              show: true,
              newItem: backendData,
              existingItem: detail.existing_item,
              existingId: detail.existing_id
            });
            return; // Don't close onboarding, user will decide
          } else {
            console.error("Cloud sync failed:", err.message);
            toast.error("Item saved locally. Cloud sync failed.");
            setShowOnboarding(false);
            await loadInventory();
          }
        }
      } else if (!isOnline) {
        toast.success("Item saved locally. Will sync when online.");
        setShowOnboarding(false);
        await loadInventory();
      } else {
        toast("Please log in to save to cloud.", { icon: '⚠️' });
      }
    } catch (error) {
      console.error(error);
      toast.error("Failed to save item");
    }
  };

  const handleComparisonUpdate = async () => {
    if (!comparisonModal.existingId) return;
    setComparisonLoading(true);
    try {
      // Prepare data: convert Blob to base64 if present
      const updateData = { ...comparisonModal.newItem };

      if (updateData.extractedImageBlob) {
        const reader = new FileReader();
        reader.readAsDataURL(updateData.extractedImageBlob);

        await new Promise((resolve, reject) => {
          reader.onload = () => {
            const base64 = (reader.result as string).split(',')[1];
            updateData.extracted_image_bytes = base64;
            updateData.image_processing = updateData.imageProcessing;
            delete updateData.extractedImageBlob;
            delete updateData.imageProcessing;
            resolve(null);
          };
          reader.onerror = reject;
        });
      }

      // Update existing item
      await inventoryApi.updateItem(comparisonModal.existingId, updateData);
      toast.success("Item updated successfully!");
      setComparisonModal({ show: false, newItem: null, existingItem: null, existingId: null });
      setShowOnboarding(false);
      await loadInventory();
    } catch (err: any) {
      console.error("Update failed:", err.message);
      toast.error("Failed to update item");
    } finally {
      setComparisonLoading(false);
    }
  };

  const handleComparisonSkip = () => {
    // Item was already added to local DB, just close modal and onboarding
    setComparisonModal({ show: false, newItem: null, existingItem: null, existingId: null });
    setShowOnboarding(false);
    toast("Local copy saved. Not synced to cloud.", { icon: '💾' });
    loadInventory();
  };

  const handleUpdateItem = async () => {
    if (!selectedItem) return;
    try {
      const updated = { ...selectedItem, ...editedItem };
      // Normalize PN
      if (updated.part_number) updated.part_number = updated.part_number.toLowerCase();

      await db.items.update(selectedItem.id!, updated);

      if (isOnline) {
        await inventoryApi.updateItem(selectedItem.id!, updated);
      }

      toast.success("Item updated successfully");
      setIsEditing(false);
      setSelectedItem(updated as Item);
      await loadInventory();
    } catch (err: any) {
      console.error(err);
      toast.error("Failed to update item");
    }
  };

  const handleDeleteItem = async () => {
    if (!selectedItem || !selectedItem.id) return;
    if (!window.confirm(`Are you sure you want to delete "${selectedItem.name}" completely from the catalog?`)) return;

    try {
      await db.items.delete(selectedItem.id);
      if (isOnline) {
        await inventoryApi.deleteItem(selectedItem.id);
      }
      toast.success("Item deleted from catalog");
      setSelectedItem(null);
      await loadInventory();
    } catch (err: any) {
      console.error(err);
      toast.error("Failed to delete item");
    }
  };


  const [searchQuery, setSearchQuery] = useState('');

  const filteredInventory = inventory.filter(item => {
    const query = searchQuery.toLowerCase();
    return (
      item.name.toLowerCase().includes(query) ||
      item.category.toLowerCase().includes(query) ||
      (item.description?.toLowerCase().includes(query) ?? false) ||
      (item.connector?.toLowerCase().includes(query) ?? false) ||
      (item.size?.toLowerCase().includes(query) ?? false) ||
      (item.part_number?.toLowerCase().includes(query) ?? false) ||
      (item.color?.toLowerCase().includes(query) ?? false) ||
      (item.box_label?.toLowerCase().includes(query) ?? false) ||
      (item.ocr_text?.toLowerCase().includes(query) ?? false)
    );
  });

  // Extract unique item types and box labels for suggestions
  const existingTypes = Array.from(new Set(inventory.map(i => i.type).filter(Boolean))).sort() as string[];
  const existingBoxes = Array.from(new Set(inventory.map(i => i.box_label).filter(Boolean))).sort() as string[];

  if (!mounted) return null;

  return (
    <PageShell>
      <div className="p-4 md:p-8 overflow-x-hidden w-full max-w-7xl mx-auto">
        {/* Search datalists for autocomplete */}
      <datalist id="existing-types">
        {existingTypes.map(t => <option key={t} value={t} />)}
      </datalist>
      <datalist id="existing-boxes">
        {existingBoxes.map(b => <option key={b} value={b} />)}
      </datalist>

        {/* Header */}
        <header className="flex flex-col sm:flex-row justify-between sm:items-center gap-3 md:gap-4 mb-6 md:mb-8 w-full">
          <div className="flex items-center gap-4">
            <div className="p-4 bg-primary/10 border border-primary/20">
              <img
                src="/logo.png"
                alt="TFM aInventory"
                className="h-8 md:h-10 object-contain"
              />
            </div>
            <div>
              <h1 className="text-2xl md:text-3xl font-normal tracking-tight text-white leading-tight">TFM aInventory</h1>
              <p className="text-xs md:text-sm text-secondary font-normal tracking-tight mt-1 leading-relaxed">Check-in, Check-out & Trash Operations</p>
            </div>
          </div>

          <div className="flex flex-wrap items-center justify-between sm:justify-end gap-2 md:gap-3 bg-surface/50 sm:bg-transparent px-3 py-2 sm:p-0 border border-border/50 sm:border-none">
            <div className="flex flex-wrap items-center gap-2 md:gap-3">
              {isScannerReady && (
                <div className="flex items-center gap-2">
                  <div className="w-1.5 h-1.5 bg-green-500" />
                  <span className="text-xs font-normal text-green-500/90 whitespace-nowrap">
                    Scanner: OK
                  </span>
                </div>
              )}
              <div className="flex items-center gap-2" data-testid={!isOnline ? "offline-indicator" : undefined}>
                <div className={`w-1.5 h-1.5 ${isOnline ? 'bg-green-500 animate-pulse' : 'bg-rose-500'}`} />
                <span className={`text-xs font-normal whitespace-nowrap ${isOnline ? 'text-green-500/90' : 'text-rose-500/90'}`} data-testid={!isOnline ? "offline-sync-indicator" : undefined}>
                  Sync: {isOnline ? 'Active' : 'Offline'}
                </span>
              </div>
            </div>
            <div className="flex items-center gap-2">
              <button
                onClick={() => setShowSearch(true)}
                className="p-2.5 bg-surface border border-border text-secondary hover:text-white transition-all active:scale-95"
                title="Search (Ctrl+K)"
              >
                <Search size={18} />
              </button>
              <button
                onClick={handleSync}
                disabled={syncing}
                data-testid="manual-sync-button"
                className="p-2.5 bg-surface border border-border text-secondary hover:text-white transition-all active:scale-95 disabled:opacity-50"
              >
                <RefreshCw size={18} className={syncing ? "animate-spin text-primary" : ""} />
              </button>
            </div>
          </div>
        </header>

        <ScannerSection
          mode={mode}
          onModeChange={(newMode) => setMode(newMode as any)}
          showScanner={showScanner}
          onShowScanner={setShowScanner}
          onScanSuccess={onScanSuccess}
          onOCRMatch={onOCRMatch}
          onAddItemClick={() => setShowOnboarding(true)}
        />

        {/* Onboarding Overlay */}
        {showOnboarding && (
          <AIOnboarding
            categories={categories}
            inventory={inventory}
            onCancel={() => setShowOnboarding(false)}
            onComplete={handleOnboardingComplete}
          />
        )}

        {/* Item Comparison Modal (for duplicate Part Numbers) */}
        <ItemComparisonModal
          show={comparisonModal.show}
          existingItem={comparisonModal.existingItem}
          newItem={comparisonModal.newItem}
          onUpdate={handleComparisonUpdate}
          onSkip={handleComparisonSkip}
          loading={comparisonLoading}
        />

        {/* Search Modal */}
        <SearchModal
          isOpen={showSearch}
          onClose={() => setShowSearch(false)}
          onSelectItem={(item) => {
            setSelectedItem(item);
            setShowSearch(false);
          }}
        />

        {/* Stock Adjustment Panel */}
        <StockAdjustmentPanel
          selectedItem={selectedItem}
          isEditing={isEditing}
          editedItem={editedItem}
          adjustQty={adjustQty}
          adjustType={adjustType}
          trashReason={trashReason}
          categories={categories}
          fieldScanning={fieldScanning}
          onCancel={() => {
            setSelectedItem(null);
            setIsEditing(false);
          }}
          onEdit={(item) => {
            setEditedItem(item);
            setIsEditing(true);
          }}
          onEditChange={setEditedItem}
          onQuantityChange={setAdjustQty}
          onTypeChange={setAdjustType}
          onReasonChange={setTrashReason}
          onShowScanner={(active, field) => {
            setFieldScanning({ active, field });
            setShowScanner(true);
          }}
          onAdjustStock={handleAdjustStock}
          onUpdateItem={handleUpdateItem}
          onDeleteItem={handleDeleteItem}
        />



        {/* Box Contents Selection Modal */}
      {boxMatches.length > 0 && !selectedItem && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4 bg-background/80 animate-in fade-in duration-200">
          <div className="w-full max-w-lg bg-surface border border-border p-4 md:p-6 overflow-hidden animate-in slide-in-from-bottom-10 duration-300 flex flex-col max-h-[85vh]">
            <div className="flex justify-between items-center mb-3 md:mb-4 shrink-0">
              <div>
                <h3 className="text-xl font-normal tracking-tight flex items-center gap-2">
                  <Package className="text-primary" />
                  Box Contents
                </h3>
                <p className="text-xs text-secondary font-normal mt-1">Select the item you want to {mode.replace('_', ' ').toLowerCase()}</p>
              </div>
              <button onClick={() => setBoxMatches([])} className="p-2 lg:p-3 xl:p-4 lg:p-5 xl:p-6 lg:p-8 xl:p-10 hover:bg-surface-bright">
                <X size={20} />
              </button>
            </div>
                      <div className="overflow-y-auto w-full pr-2 space-y-2 md:space-y-3 pb-3 md:pb-4">
              {boxMatches.map(item => (
                <button
                  key={item.id}
                  onClick={() => {
                    setSelectedItem(item);
                    setBoxMatches([]);
                    setAdjustType(mode === 'CHECK_IN' ? 'ADD' : 'REMOVE');
                  }}
                  className="w-full text-left bg-background/50 hover:bg-surface-bright border border-border/80 p-3 md:p-4 flex items-center gap-2 md:gap-3 transition-all active:scale-[0.98] group"
                >
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-normal text-white">{item.name}</p>
                    <p className="text-xs text-secondary font-normal mt-1">Part #: {item.part_number || 'N/A'}</p>
                  </div>
                  <ChevronRight size={18} className="text-secondary group-hover:text-primary" />
                </button>
              ))}
            </div>
          </div>
        </div>
      )}


      {/* Footer Branding */}
        <footer className="mt-12 md:mt-20 mb-4 md:mb-8 flex flex-col items-center gap-2 opacity-70">
          <p className="text-sm font-normal text-secondary">Powered by TFM Group Software</p>
          <div className="h-px w-16 bg-[#222222]/60" />
          <p className="text-xs lg:text-sm xl:text-base lg:text-lg xl:text-xl lg:text-2xl xl:text-3xl lg:text-4xl xl:text-5xl font-mono text-secondary">v{versionData.version} • {versionData.last_build} • BUILD: dev-{(versionData as any).commit || 'N/A'}</p>
        </footer>
      </div>
    </PageShell>
  );
}
