import React, { useRef, useState, useEffect, useCallback } from 'react';
import { Camera, X, Zap, ZapOff, Image as ImageIcon, RotateCcw, Loader2, AlertTriangle } from 'lucide-react';

interface Props {
  onCapture: (file: File) => void;
  onClose: () => void;
  title?: string;
  allowGallery?: boolean;
}

// Resolução baixa só para análise de movimento/reflexo (leve no celular).
const AW = 80, AH = 60;

/**
 * Captura por câmera no NAVEGADOR (getUserMedia). Recursos:
 * - Câmera traseira ao vivo, guia de enquadramento.
 * - Auto-disparo quando a imagem fica ESTÁVEL (anti-tremor) — opcional (botão AUTO).
 * - Detecção de REFLEXO (estouro de luz) avisando para reposicionar.
 * - Lanterna (torch) onde o navegador suporta (Android/Chrome).
 * - Fallback para galeria/arquivo.
 * Observação: requer HTTPS (dev.scoreodonto.com já é).
 */
export const CameraCapture: React.FC<Props> = ({ onCapture, onClose, title, allowGallery = true }) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const captureCanvas = useRef<HTMLCanvasElement | null>(null);
  const analysisCanvas = useRef<HTMLCanvasElement | null>(null);
  const prevGray = useRef<Float32Array | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const rafRef = useRef<number>(0);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const stableCountRef = useRef(0);
  const capturedRef = useRef(false);

  const [facing, setFacing] = useState<'environment' | 'user'>('environment');
  const [error, setError] = useState('');
  const [ready, setReady] = useState(false);
  const [torchSupported, setTorchSupported] = useState(false);
  const [torchOn, setTorchOn] = useState(false);
  const [auto, setAuto] = useState(true);
  const [hint, setHint] = useState('INICIANDO CÂMERA…');
  const [steady, setSteady] = useState(false);

  const cvs = (r: React.MutableRefObject<HTMLCanvasElement | null>) => (r.current ??= document.createElement('canvas'));

  const stop = useCallback(() => {
    cancelAnimationFrame(rafRef.current);
    streamRef.current?.getTracks().forEach(t => t.stop());
    streamRef.current = null;
  }, []);

  const start = useCallback(async (mode: 'environment' | 'user') => {
    setError(''); setReady(false); prevGray.current = null; stableCountRef.current = 0; capturedRef.current = false;
    stop();
    if (!navigator.mediaDevices?.getUserMedia) { setError('CÂMERA NÃO SUPORTADA NESTE NAVEGADOR.'); return; }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: { ideal: mode }, width: { ideal: 1920 }, height: { ideal: 1080 } },
        audio: false,
      });
      streamRef.current = stream;
      const v = videoRef.current;
      if (v) { v.srcObject = stream; await v.play().catch(() => {}); }
      const track = stream.getVideoTracks()[0];
      const caps: any = track.getCapabilities ? track.getCapabilities() : {};
      setTorchSupported(!!caps.torch);
      setTorchOn(false);
      setReady(true);
      setHint('ENQUADRE E SEGURE FIRME');
    } catch (e: any) {
      setError(
        e?.name === 'NotAllowedError' ? 'PERMISSÃO DE CÂMERA NEGADA.' :
        e?.name === 'NotFoundError' ? 'NENHUMA CÂMERA ENCONTRADA.' :
        'NÃO FOI POSSÍVEL ABRIR A CÂMERA.'
      );
    }
  }, [stop]);

  useEffect(() => { start(facing); return stop; /* eslint-disable-next-line */ }, []);

  const toGray = (v: HTMLVideoElement): Float32Array => {
    const c = cvs(analysisCanvas); c.width = AW; c.height = AH;
    const ctx = c.getContext('2d', { willReadFrequently: true })!;
    ctx.drawImage(v, 0, 0, AW, AH);
    const d = ctx.getImageData(0, 0, AW, AH).data;
    const g = new Float32Array(AW * AH);
    for (let i = 0, j = 0; i < d.length; i += 4, j++) g[j] = d[i] * 0.299 + d[i + 1] * 0.587 + d[i + 2] * 0.114;
    return g;
  };

  const capture = useCallback(() => {
    if (capturedRef.current) return;
    const v = videoRef.current;
    if (!v || !v.videoWidth) return;
    capturedRef.current = true;
    const c = cvs(captureCanvas); c.width = v.videoWidth; c.height = v.videoHeight;
    c.getContext('2d')!.drawImage(v, 0, 0);
    c.toBlob(blob => {
      if (!blob) { capturedRef.current = false; return; }
      onCapture(new File([blob], `foto_${Date.now()}.jpg`, { type: 'image/jpeg' }));
      stop(); onClose();
    }, 'image/jpeg', 0.92);
  }, [onCapture, onClose, stop]);

  // Loop de análise: estabilidade + reflexo + auto-disparo
  useEffect(() => {
    if (!ready) return;
    let last = 0;
    const loop = (ts: number) => {
      rafRef.current = requestAnimationFrame(loop);
      if (ts - last < 120) return;
      last = ts;
      const v = videoRef.current;
      if (!v || !v.videoWidth || capturedRef.current) return;
      const g = toGray(v);
      let bright = 0;
      for (let i = 0; i < g.length; i++) if (g[i] > 245) bright++;
      const glare = bright / g.length;
      let motion = 999;
      if (prevGray.current) {
        let sum = 0;
        for (let i = 0; i < g.length; i++) sum += Math.abs(g[i] - prevGray.current[i]);
        motion = sum / g.length;
      }
      prevGray.current = g;
      const isSteady = motion < 5;
      setSteady(isSteady && glare <= 0.18);
      if (glare > 0.18) { setHint('REFLEXO DETECTADO — INCLINE OU AFASTE A LUZ'); stableCountRef.current = 0; return; }
      if (!isSteady) { setHint('SEGURE FIRME…'); stableCountRef.current = 0; return; }
      stableCountRef.current++;
      setHint(auto ? 'ESTÁVEL — CAPTURANDO…' : 'ESTÁVEL — TOQUE NO BOTÃO');
      if (auto && stableCountRef.current >= 4) capture();
    };
    rafRef.current = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(rafRef.current);
  }, [ready, auto, capture]);

  const toggleTorch = async () => {
    const track = streamRef.current?.getVideoTracks()[0];
    if (!track) return;
    try { await track.applyConstraints({ advanced: [{ torch: !torchOn }] as any }); setTorchOn(t => !t); } catch { /* ignore */ }
  };

  const onPickFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const f = e.target.files?.[0];
    if (f) { stop(); onCapture(f); onClose(); }
  };

  return (
    <div className="fixed inset-0 bg-black z-[90] flex flex-col select-none">
      <div className="flex items-center justify-between px-4 py-3 text-white flex-shrink-0">
        <span className="text-xs font-black uppercase truncate">{title || 'CÂMERA'}</span>
        <button onClick={() => { stop(); onClose(); }} className="p-2 hover:bg-white/10 rounded-lg"><X size={20} /></button>
      </div>

      <div className="flex-1 relative min-h-0 flex items-center justify-center overflow-hidden">
        {error ? (
          <div className="text-center text-white/80 px-6">
            <AlertTriangle size={36} className="mx-auto mb-3 text-amber-400" />
            <p className="text-sm font-bold uppercase">{error}</p>
            {allowGallery && (
              <button onClick={() => fileInputRef.current?.click()} className="mt-4 px-4 py-2 bg-white/10 rounded-xl text-xs font-black uppercase">
                Usar galeria
              </button>
            )}
          </div>
        ) : (
          <>
            <video ref={videoRef} playsInline muted className="max-w-full max-h-full object-contain" />
            {!ready && <Loader2 size={32} className="absolute animate-spin text-white/60" />}
            {ready && <div className={`absolute inset-6 border-2 rounded-2xl pointer-events-none transition-colors duration-200 ${steady ? 'border-emerald-400' : 'border-white/40'}`} />}
            {ready && (
              <div className={`absolute bottom-4 left-1/2 -translate-x-1/2 text-[11px] font-black uppercase px-3 py-1.5 rounded-full ${steady ? 'bg-emerald-500 text-white' : 'bg-black/60 text-white'}`}>
                {hint}
              </div>
            )}
          </>
        )}
      </div>

      <div className="flex items-center justify-between px-6 py-5 gap-3 flex-shrink-0">
        <div className="flex gap-2 w-24">
          {allowGallery && (
            <button onClick={() => fileInputRef.current?.click()} className="p-3 bg-white/10 text-white rounded-full" title="Galeria"><ImageIcon size={20} /></button>
          )}
          {torchSupported && (
            <button onClick={toggleTorch} className={`p-3 rounded-full ${torchOn ? 'bg-amber-400 text-black' : 'bg-white/10 text-white'}`} title="Lanterna">
              {torchOn ? <Zap size={20} /> : <ZapOff size={20} />}
            </button>
          )}
        </div>
        <button onClick={capture} disabled={!ready} className="w-16 h-16 rounded-full bg-white border-4 border-white/40 disabled:opacity-40 flex items-center justify-center active:scale-95 transition-transform">
          <Camera size={26} className="text-gray-800" />
        </button>
        <div className="flex gap-2 w-24 justify-end">
          <button onClick={() => setAuto(a => !a)} className={`px-3 py-2 rounded-full text-[10px] font-black uppercase ${auto ? 'bg-emerald-500 text-white' : 'bg-white/10 text-white'}`} title="Auto-disparo quando firme">AUTO</button>
          <button onClick={() => { const m = facing === 'environment' ? 'user' : 'environment'; setFacing(m); start(m); }} className="p-3 bg-white/10 text-white rounded-full" title="Trocar câmera"><RotateCcw size={20} /></button>
        </div>
      </div>

      {allowGallery && <input ref={fileInputRef} type="file" accept="image/*" capture="environment" className="hidden" onChange={onPickFile} />}
    </div>
  );
};
