'use client';

import { useEffect, useRef, useState } from 'react';
import { Html5Qrcode, Html5QrcodeSupportedFormats } from 'html5-qrcode';
import { RefreshCw, XCircle, Search } from 'lucide-react';
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 [ocrProcessing, setOcrProcessing] = useState(false);
  const [countdown, setCountdown] = useState(4);
  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 isTransitioning = useRef(false); // Flag to track start/stop transitions
  const scannerId = "reader-container-unique";

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

    const startScanner = async () => {
      if (isBusy.current || isTransitioning.current) return;
      isBusy.current = true;
      isTransitioning.current = true;

      try {
        // If already scanning, we MUST stop it first
        if (html5QrCodeRef.current?.isScanning) {
            try {
              await html5QrCodeRef.current.stop();
            } catch (e) {
              console.warn("Graceful stop failed, might be in transition:", e);
              // If it's already in transition, we just return and wait for the next effect trigger
              return;
            }
        }

        const config = { 
          fps: 15,
          qrbox: { width: 320, height: 320 },
          aspectRatio: 1.0,
          formatsToSupport: [
              Html5QrcodeSupportedFormats.QR_CODE,
              Html5QrcodeSupportedFormats.CODE_128,
              Html5QrcodeSupportedFormats.CODE_39,
              Html5QrcodeSupportedFormats.EAN_13,
              Html5QrcodeSupportedFormats.UPC_A,
              Html5QrcodeSupportedFormats.DATA_MATRIX
          ],
          videoConstraints: {
            facingMode: "environment"
          }
        };

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

        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;
        isTransitioning.current = false;
      }
    };

    if (!paused) {
      startScanner();
    }

    return () => {
      if (html5QrCodeRef.current?.isScanning) {
        isTransitioning.current = true;
        html5QrCodeRef.current.stop()
            .then(() => {
                setIsStarted(false);
            })
            .catch(e => console.error("Unmount stop failed", e))
            .finally(() => {
                isTransitioning.current = false;
            });
      }
    };
  }, [paused, onScanSuccess]);

  // Automated OCR Countdown Timer
  useEffect(() => {
    if (!isStarted || paused || isSelecting || ocrProcessing) {
      return;
    }

    const timer = setInterval(() => {
      setCountdown(prev => {
        if (prev <= 1) {
          handleOCR();
          return 4; // Reset to 4
        }
        return prev - 1;
      });
    }, 1000);

    return () => clearInterval(timer);
  }, [isStarted, paused, isSelecting, ocrProcessing]);

  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;
      
      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;
      
      const ctx = canvas.getContext('2d');
      if (ctx) {
        ctx.filter = 'grayscale(100%) contrast(180%) brightness(105%)';
        ctx.drawImage(video, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height);
      }

      // Lazy-load tesseract.js only when OCR is actually needed
      const { createWorker } = await import('tesseract.js');
      const workerPromise = createWorker('eng');
      const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("OCR Engine timeout")), 20000));

      const worker = await Promise.race([workerPromise, timeoutPromise]) as any;
      const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
      
      setCapturedImage(dataUrl);

      const result = await worker.recognize(dataUrl);
      const data = result.data;
      
      if (data && data.text && (!data.words || data.words.length === 0)) {
         onOCRMatch?.(data.text);
         await worker.terminate();
         setCapturedImage(null);
         return;
      }

      if (!data || !data.words || data.words.length === 0) {
         await worker.terminate();
         setCapturedImage(null);
         return;
      }

      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);
    } finally {
      setOcrProcessing(false);
    }
  };

  const handleWordSelect = (text: string) => {
    onOCRMatch?.(text);
    setIsSelecting(false);
    setCapturedImage(null);
    setDetectedWords([]);
    setCountdown(4); // Restart countdown
  };

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

  return (
    <div className="w-full max-w-md mx-auto flex flex-col gap-6">
      {/* Video Viewport Area */}
      <div className="relative w-full aspect-square overflow-hidden rounded-[2.5rem] shadow-[0_20px_50px_rgba(0,0,0,0.5)] bg-background border-2 border-slate-800/50 p-4 sm:p-6">
        <div className="absolute inset-4 sm:inset-6 z-10 pointer-events-none flex items-center justify-center">
          <div className="w-full h-full border border-primary/30 rounded-[2rem] relative">
            <div className="absolute top-0 left-0 w-10 h-10 border-t-4 border-l-4 border-primary rounded-tl-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
            <div className="absolute top-0 right-0 w-10 h-10 border-t-4 border-r-4 border-primary rounded-tr-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
            <div className="absolute bottom-0 left-0 w-10 h-10 border-b-4 border-l-4 border-primary rounded-bl-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
            <div className="absolute bottom-0 right-0 w-10 h-10 border-b-4 border-r-4 border-primary rounded-br-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
            
            {isStarted && !paused && !isSelecting && (
                 <div className="absolute top-0 left-0 right-0 h-1 bg-primary animate-scan-fast" />
            )}
          </div>
        </div>

        <div id={scannerId} className="w-full h-full bg-surface object-cover" />

        {/* Selection UI */}
        {isSelecting && capturedImage && (
          <div className="absolute inset-0 z-50 bg-background flex flex-col">
            <div className="relative flex-1 bg-black flex items-center justify-center overflow-hidden">
               <img
                 src={capturedImage || undefined}
                 className="max-w-full max-h-full object-contain"
                 id="ocr-canvas-preview"
                 alt="OCR text detection preview with detected words highlighted"
               />
               <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)}
                        aria-label={`Select text: ${w.text}`}
                        className="absolute border border-primary bg-primary/20 rounded-sm active:bg-primary/50 cursor-pointer transition-colors pointer-events-auto focus:ring-2 focus:ring-primary focus:outline-none"
                        style={{
                          left: `${(w.bbox.x0 / 1600) * 100}%`,
                          top: `${(w.bbox.y0 / (1600 * (9/16))) * 100}%`,
                          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-surface/90 border-t border-slate-800 flex flex-col gap-4">
               <div className="flex flex-col items-center gap-1">
                 <p className="text-sm font-black text-white italic text-center">Text Found</p>
                 <p className="text-xs text-muted font-black text-center">Tap any text to use it</p>
               </div>
               <button
                 onClick={() => { setIsSelecting(false); setCapturedImage(null); setCountdown(4); }}
                 aria-label="Cancel text selection"
                 className="w-full py-4 bg-slate-800 hover:bg-slate-700 text-white rounded-2xl font-black text-xs cursor-pointer transition-all active:scale-95 border border-slate-700 focus:ring-2 focus:ring-blue-500 focus:outline-none"
               >
                 Cancel
               </button>
            </div>
          </div>
        )}

        {!isStarted && !error && (
          <div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-surface 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-surface 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-secondary mt-1">{error}</p>
            </div>
            <button
              onClick={() => window.location.reload()}
              aria-label="Reload page and try again"
              className="mt-4 px-6 py-2 bg-slate-800 rounded-full text-sm font-bold cursor-pointer hover:bg-slate-700 transition-colors focus:ring-2 focus:ring-blue-500 focus:outline-none"
            >
              Try Again
            </button>
          </div>
        )}
      </div>

      {/* External Controls Area */}
      <div className="flex flex-col gap-4 bg-surface/50 p-5 rounded-[2.5rem] border border-slate-800/50 shadow-2xl">
        <div className="flex items-center gap-3 w-full">
            {hasZoom && (
              <button
                onClick={async () => {
                  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);
                  }
                }}
                aria-label={`Zoom ${zoom.toFixed(1)}x`}
                className="h-14 px-5 bg-slate-800/80 hover:bg-slate-700 border border-slate-700 text-white rounded-2xl flex flex-col items-center justify-center shadow-lg cursor-pointer transition-all active:scale-95 shrink-0 focus:ring-2 focus:ring-blue-500 focus:outline-none"
              >
                <span className="text-xs font-black tabular-nums">{zoom.toFixed(1)}x</span>
                <span className="text-xs text-primary font-black tracking-tighter">Zoom</span>
              </button>
            )}

            <div className="flex-1 h-14 bg-background/40 border border-slate-800/50 rounded-2xl flex items-center justify-center gap-3 px-4 relative overflow-hidden group">
                {ocrProcessing ? (
                  <>
                    <RefreshCw className="animate-spin text-primary" size={18} />
                    <span className="text-xs font-black text-slate-200 leading-none">Analyzing</span>
                  </>
                ) : (
                  <>
                    <Search className={cn("text-secondary transition-colors group-hover:text-primary", !isStarted && "opacity-20")} size={18} />
                    <div className="flex flex-col">
                        <span className="text-xs text-muted font-black leading-none">Smart Scan</span>
                        <span className="text-xs font-black text-primary leading-tight tabular-nums">
                            {countdown === 0 ? "Scanning" : `${countdown}s`}
                        </span>
                    </div>
                  </>
                )}
                
                {/* Visual Progress Bar */}
                <div 
                    className="absolute bottom-0 left-0 h-0.5 bg-primary/40 transition-all duration-1000 ease-linear shadow-[0_0_10px_rgba(59,130,246,0.5)]"
                    style={{ width: `${((4 - countdown) / 4) * 100}%` }}
                />
            </div>
        </div>

        <div className="w-full flex justify-center items-center gap-2">
          <div className="w-1 h-1 rounded-full bg-green-500 animate-pulse" />
          <p className="text-xs text-secondary font-black">
            Scanner active · Use zoom or tap scan
          </p>
        </div>
      </div>
    </div>
  );
}
