'use client';

import { useEffect, useRef, useState } from 'react';
import { Html5Qrcode, Html5QrcodeSupportedFormats } from 'html5-qrcode';
import { Camera, RefreshCw, XCircle, Type, Search } from 'lucide-react';
import { createWorker } from 'tesseract.js';
import { toast } from 'react-hot-toast';

interface ScannerProps {
  onScanSuccess: (decodedText: string) => void;
  onOCRMatch?: (text: string) => void;
  paused?: boolean;
}

export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerProps) {
  const html5QrCodeRef = useRef<Html5Qrcode | null>(null);
  const [isStarted, setIsStarted] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isOCRMode, setIsOCRMode] = useState(false);
  const [ocrProcessing, setOcrProcessing] = useState(false);
  const [zoom, setZoom] = useState(1);
  const [maxZoom, setMaxZoom] = useState(1);
  const [hasZoom, setHasZoom] = useState(false);
  const [detectedWords, setDetectedWords] = useState<{ text: string, bbox: { x0: number, y0: number, x1: number, y1: number } }[]>([]);
  const [isSelecting, setIsSelecting] = useState(false);
  const [capturedImage, setCapturedImage] = useState<string | null>(null);
  const isBusy = useRef(false);
  const scannerId = "reader-container-unique";

  useEffect(() => {
    if (!html5QrCodeRef.current) {
        html5QrCodeRef.current = new Html5Qrcode(scannerId);
    }

    const startScanner = async () => {
      if (isBusy.current) return;
      isBusy.current = true;
      try {
        if (html5QrCodeRef.current?.isScanning) {
            await html5QrCodeRef.current.stop();
        }

        const config = { 
          fps: 15, // Lower FPS for stability
          qrbox: { width: 280, height: 280 },
          aspectRatio: 1.0,
          formatsToSupport: [
              Html5QrcodeSupportedFormats.QR_CODE,
              Html5QrcodeSupportedFormats.CODE_128,
              Html5QrcodeSupportedFormats.CODE_39,
              Html5QrcodeSupportedFormats.EAN_13,
              Html5QrcodeSupportedFormats.UPC_A,
              Html5QrcodeSupportedFormats.DATAMATRIX
          ],
          // Simplified constraints for maximum compatibility
          videoConstraints: {
            facingMode: "environment"
          }
        };

        await html5QrCodeRef.current?.start(
          { facingMode: "environment" },
          config,
          (decodedText) => {
            onScanSuccess(decodedText);
          },
          () => {} // Ignore frame errors
        );

        // Check for zoom capability via video track
        const video = document.querySelector(`#${scannerId} video`) as HTMLVideoElement;
        const track = (video?.srcObject as MediaStream)?.getVideoTracks()[0];
        const caps = track?.getCapabilities() as any;
        if (track && caps?.zoom) {
          setHasZoom(true);
          setMaxZoom(caps.zoom.max || 3);
        }

        setIsStarted(true);
        setError(null);
      } catch (err: any) {
        const errorMsg = String(err);
        if (!errorMsg.includes("is already starting") && !errorMsg.includes("already under transition")) {
            console.error("Scanner failed", err);
            setError(errorMsg || "Failed to access camera");
            setIsStarted(false);
        }
      } finally {
        isBusy.current = false;
      }
    };

    if (!paused) {
      startScanner();
    }

    return () => {
      if (html5QrCodeRef.current?.isScanning) {
        html5QrCodeRef.current.stop()
            .then(() => {
                setIsStarted(false);
            })
            .catch(e => console.error("Stop failed", e));
      }
    };
  }, [paused, onScanSuccess]); // Minimal deps

  // Separate effect for OCR interval to avoid restarting scanner
  useEffect(() => {
    let intervalId: any;
    if (isOCRMode && isStarted && !paused) {
      intervalId = setInterval(() => {
        handleOCR();
      }, 5000); // 5 seconds is safer
    }
    return () => {
      if (intervalId) clearInterval(intervalId);
    };
  }, [isOCRMode, isStarted, paused]);

  const handleOCR = async () => {
    if (ocrProcessing) return;
    setOcrProcessing(true);
    try {
      const video = document.querySelector(`#${scannerId} video`) as HTMLVideoElement;
      if (!video) return;

      const canvas = document.createElement('canvas');
      
      const vWidth = video.videoWidth || 1280;
      const vHeight = video.videoHeight || 720;
      
      // Digital Zoom/Crop: 60% of center
      const cropFactor = 0.6;
      const sw = vWidth * cropFactor;
      const sh = vHeight * cropFactor;
      const sx = (vWidth - sw) / 2;
      const sy = (vHeight - sh) / 2;

      canvas.width = 1200; 
      canvas.height = (sh / sw) * 1200;
      
      console.log(`OCR Capture: ${vWidth}x${vHeight} -> ${canvas.width}x${canvas.height}`);

      const ctx = canvas.getContext('2d');
      if (ctx) {
        // More balanced filter for both paper and metal labels
        ctx.filter = 'grayscale(100%) contrast(180%) brightness(105%)';
        ctx.drawImage(video, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height);
      }

      // Timeout protection for worker initialization (especially when offline for first run)
      const workerPromise = createWorker('eng');
      const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("OCR Engine timeout - check internet for first run")), 8000));
      
      const worker = await Promise.race([workerPromise, timeoutPromise]) as any;
      const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
      
      // DIAGNOSTIC: Set captured image early so user can see what was sent to AI
      setCapturedImage(dataUrl);

      const result = await worker.recognize(dataUrl);
      console.log("OCR Result Size:", result.data?.text?.length);

      const data = result.data;
      
      // FALLBACK: If we have text but no word coordinates
      if (data && data.text && (!data.words || data.words.length === 0)) {
         console.log("Fallback to direct match");
         onOCRMatch(data.text);
         await worker.terminate();
         setCapturedImage(null);
         return;
      }

      if (!data || !data.words || data.words.length === 0) {
         console.warn("OCR produced no text or words.");
         toast.error("Label not readable. Try better light or zoom.");
         await worker.terminate();
         setCapturedImage(null);
         return;
      }

      // Store words with their bounding boxes
      const words = data.words.map((w: any) => ({
        text: w.text,
        bbox: w.bbox
      }));

      setDetectedWords(words);
      setIsSelecting(true);
      await worker.terminate();
    } catch (err) {
      console.error("OCR failed", err);
      toast.error("OCR selection failed");
    } finally {
      setOcrProcessing(false);
    }
  };

  const handleWordSelect = (text: string) => {
    onOCRMatch(text);
    // Reset selection state
    setIsSelecting(false);
    setCapturedImage(null);
    setDetectedWords([]);
  };

  const cn = (...classes: any[]) => classes.filter(Boolean).join(' ');

  return (
    <div className="relative w-full max-w-[340px] mx-auto overflow-hidden rounded-[2.5rem] shadow-2xl bg-black border-[3px] border-slate-800 shadow-blue-500/10">
      <div className="absolute inset-0 z-10 pointer-events-none flex items-center justify-center">
        <div className="w-[280px] h-[280px] border-2 border-primary/50 rounded-3xl relative">
          <div className="absolute top-0 left-0 w-8 h-8 border-t-4 border-l-4 border-primary rounded-tl-xl" />
          <div className="absolute top-0 right-0 w-8 h-8 border-t-4 border-r-4 border-primary rounded-tr-xl" />
          <div className="absolute bottom-0 left-0 w-8 h-8 border-b-4 border-l-4 border-primary rounded-bl-xl" />
          <div className="absolute bottom-0 right-0 w-8 h-8 border-b-4 border-r-4 border-primary rounded-br-xl" />
          <div className="absolute top-0 left-0 right-0 h-0.5 bg-primary/50 shadow-[0_0_15px_rgba(59,130,246,0.8)] animate-scan-fast" />
        </div>
      </div>

      <div id={scannerId} className="w-full aspect-square bg-slate-900" />

      <div className="absolute top-4 right-4 z-30 flex gap-2">
        <button 
          onClick={() => setIsOCRMode(!isOCRMode)}
          className={cn(
            "p-2 rounded-xl border backdrop-blur-md transition-all",
            isOCRMode ? "bg-primary border-primary text-white shadow-lg" : "bg-slate-900/50 border-slate-700 text-slate-300"
          )}
        >
          <Type size={18} />
        </button>
      </div>

      {/* Selection UI */}
      {isSelecting && capturedImage && (
        <div className="absolute inset-0 z-50 bg-slate-950 flex flex-col">
          <div className="relative flex-1 bg-black flex items-center justify-center overflow-hidden">
             <img src={capturedImage} className="max-w-full max-h-full object-contain" id="ocr-canvas-preview" />
             {/* Render Bounding Boxes */}
             <div className="absolute inset-0 flex items-center justify-center">
                <div className="relative" style={{ width: '100%', height: '100%' }}>
                  {detectedWords.map((w, i) => (
                    <button
                      key={i}
                      onClick={() => handleWordSelect(w.text)}
                      className="absolute border border-primary bg-primary/20 rounded-sm active:bg-primary/50 transition-colors pointer-events-auto"
                      style={{
                        left: `${(w.bbox.x0 / 1600) * 100}%`,
                        top: `${(w.bbox.y0 / (1600 * (9/16))) * 100}%`, // Assuming 16:9 ratio, this may need adjustment based on real canvas aspect
                        width: `${((w.bbox.x1 - w.bbox.x0) / 1600) * 100}%`,
                        height: `${((w.bbox.y1 - w.bbox.y0) / (1600 * (9/16))) * 100}%`,
                      }}
                    />
                  ))}
                </div>
             </div>
          </div>
          <div className="p-6 bg-slate-900 border-t border-slate-800 flex flex-col gap-4">
             <p className="text-sm font-bold text-center text-primary">Tap the correct text on the label</p>
             <button 
               onClick={() => { setIsSelecting(false); setCapturedImage(null); }}
               className="w-full py-4 bg-slate-800 text-white rounded-2xl font-black text-xs uppercase tracking-widest"
             >
               Cancel & Rescan
             </button>
          </div>
        </div>
      )}

      {isOCRMode && (
        <div className="absolute inset-0 z-20 pointer-events-none border-2 border-primary/30 rounded-[2rem] animate-pulse" />
      )}

      {!isStarted && !error && (
        <div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-slate-900 text-slate-300 gap-4">
          <RefreshCw className="w-8 h-8 animate-spin text-primary" />
          <p className="text-sm font-medium">Initializing camera...</p>
        </div>
      )}

      {error && (
        <div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-slate-900 text-slate-300 px-8 text-center gap-4">
          <XCircle className="w-10 h-10 text-red-500" />
          <div>
            <p className="font-bold text-white">Camera Error</p>
            <p className="text-xs text-slate-400 mt-1">{error}</p>
          </div>
          <button 
            onClick={() => window.location.reload()}
            className="mt-4 px-6 py-2 bg-slate-800 rounded-full text-sm font-bold hover:bg-slate-700 transition-colors"
          >
            Try Again
          </button>
        </div>
      )}

      <div className="absolute bottom-6 left-0 right-0 z-30 flex flex-col items-center gap-4 px-6">
        {hasZoom && (
          <button 
            onClick={async () => {
              // Cycle through: 1x -> 2x -> Max/2 -> Max
              let nextZoom = 1;
              if (zoom === 1) nextZoom = Math.min(2, maxZoom);
              else if (zoom < maxZoom / 2) nextZoom = Math.floor(maxZoom / 2);
              else if (zoom < maxZoom) nextZoom = maxZoom;
              else nextZoom = 1;

              const video = document.querySelector(`#${scannerId} video`) as HTMLVideoElement;
              const track = (video?.srcObject as MediaStream)?.getVideoTracks()[0];
              if (track) {
                await track.applyConstraints({ advanced: [{ zoom: nextZoom }] as any });
                setZoom(nextZoom);
              }
            }}
            className="bg-slate-900/90 backdrop-blur-md border border-slate-700 text-white w-14 h-14 rounded-full flex flex-col items-center justify-center shadow-2xl active:scale-95 transition-transform"
          >
            <span className="text-xs font-black">{zoom.toFixed(1)}x</span>
            <span className="text-[8px] uppercase text-primary font-bold">Zoom</span>
          </button>
        )}

        {isOCRMode ? (
          <button 
             onClick={handleOCR}
             disabled={ocrProcessing}
             className={cn(
               "w-full py-4 rounded-2xl font-black text-xs uppercase tracking-[0.2em] flex items-center justify-center gap-3 shadow-2xl transition-all active:scale-95 border border-white/10",
               ocrProcessing ? "bg-slate-800 text-slate-500" : "bg-primary text-white"
             )}
          >
            {ocrProcessing ? <RefreshCw className="animate-spin" size={18} /> : <Search size={18} />}
            {ocrProcessing ? "Analyzing..." : "Find by Label (OCR)"}
          </button>
        ) : (
          <div className="bg-black/40 backdrop-blur-sm py-2 px-6 rounded-full border border-white/5">
            <p className="text-[10px] text-center text-slate-300 uppercase tracking-widest font-black">
              Center barcode for auto-scan
            </p>
          </div>
        )}
      </div>
    </div>
  );
}
