// b/camera.jsx — real capture: live camera (getUserMedia) + upload + drag-drop.

function Camera({ onCapture }) {
  const videoRef = React.useRef(null);
  const fileRef = React.useRef(null);
  const streamRef = React.useRef(null);
  const [status, setStatus] = React.useState('init'); // init|live|nocam|denied
  const [flash, setFlash] = React.useState(false);
  const [drag, setDrag] = React.useState(false);

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { setStatus('nocam'); return; }
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: { facingMode: { ideal: 'environment' }, width: { ideal: 1280 }, height: { ideal: 1280 } },
          audio: false,
        });
        if (cancelled) { stream.getTracks().forEach(t => t.stop()); return; }
        streamRef.current = stream;
        if (videoRef.current) { videoRef.current.srcObject = stream; await videoRef.current.play().catch(() => {}); }
        setStatus('live');
      } catch (e) {
        setStatus(e && e.name === 'NotAllowedError' ? 'denied' : 'nocam');
      }
    })();
    return () => { cancelled = true; if (streamRef.current) streamRef.current.getTracks().forEach(t => t.stop()); };
  }, []);

  const stop = () => { if (streamRef.current) streamRef.current.getTracks().forEach(t => t.stop()); };

  const snap = () => {
    if (status !== 'live' || !videoRef.current) return;
    setFlash(true);
    const shot = videoFrameToBase64(videoRef.current);
    setTimeout(() => { stop(); onCapture(shot); }, 180);
  };

  const handleFile = async (file) => {
    if (!file) return;
    const shot = await fileToCompressedBase64(file);
    stop(); onCapture(shot);
  };

  const onDrop = (e) => {
    e.preventDefault(); setDrag(false);
    const f = e.dataTransfer.files && e.dataTransfer.files[0];
    if (f) handleFile(f);
  };

  const dark = '#f7f5ee';
  return (
    <div
      onDragOver={e => { e.preventDefault(); setDrag(true); }}
      onDragLeave={() => setDrag(false)}
      onDrop={onDrop}
      style={{ position: 'absolute', inset: 0, background: T.screen, overflow: 'hidden' }}>

      {/* live video */}
      <video ref={videoRef} playsInline muted
        style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover',
          opacity: status === 'live' ? 1 : 0, transition: 'opacity .4s' }} />

      {/* fallback backdrop when no camera */}
      {status !== 'live' && (
        <div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(120% 80% at 50% 30%, #23211c 0%, #0e0d0a 100%)' }} />
      )}

      {/* vignette + framing */}
      <div style={{ position: 'absolute', inset: 0, boxShadow: 'inset 0 0 120px rgba(0,0,0,.55)', pointerEvents: 'none' }} />
      {status === 'live' && (
        <div style={{ position: 'absolute', inset: '90px 26px 170px', pointerEvents: 'none' }}>
          {['tl','tr','bl','br'].map(c => {
            const s = { position: 'absolute', width: 26, height: 26, borderColor: 'var(--accent)', borderStyle: 'solid', borderWidth: 0 };
            if (c==='tl') Object.assign(s,{top:0,left:0,borderTopWidth:3,borderLeftWidth:3});
            if (c==='tr') Object.assign(s,{top:0,right:0,borderTopWidth:3,borderRightWidth:3});
            if (c==='bl') Object.assign(s,{bottom:0,left:0,borderBottomWidth:3,borderLeftWidth:3});
            if (c==='br') Object.assign(s,{bottom:0,right:0,borderBottomWidth:3,borderRightWidth:3});
            return <span key={c} style={s} />;
          })}
        </div>
      )}

      {/* top HUD */}
      <div style={{ position: 'absolute', top: 40, left: 16, right: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', color: dark }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 7, height: 7, borderRadius: 7, background: 'var(--accent)', boxShadow: '0 0 8px var(--accent)' }} />
          <span style={{ fontFamily: mono, fontSize: 11, letterSpacing: 1 }}>BRIKLAB</span>
        </div>
        <span style={{ fontFamily: mono, fontSize: 10, opacity: .8 }}>
          {status === 'live' ? 'KAMERA AKTIVT' : status === 'init' ? 'STARTER…' : 'INTET KAMERA'}
        </span>
      </div>

      {/* no-camera / denied panel */}
      {(status === 'nocam' || status === 'denied') && (
        <div style={{ position: 'absolute', top: 90, left: 24, right: 24, color: dark, textAlign: 'center' }}>
          <div style={{ fontFamily: disp, fontSize: 17, fontWeight: 600, marginBottom: 6 }}>
            {status === 'denied' ? 'Kamera-adgang afvist' : 'Kamera ikke tilgængeligt'}
          </div>
          <div style={{ fontFamily: disp, fontSize: 13, opacity: .8, lineHeight: 1.5 }}>
            {status === 'denied'
              ? 'Tillad kamera i browseren — eller upload et billede af dine klodser herunder.'
              : 'Upload et billede af dine klodser herunder, så analyserer vi det.'}
          </div>
        </div>
      )}

      {/* guidance pill */}
      <div style={{ position: 'absolute', bottom: 150, left: '50%', transform: 'translateX(-50%)',
        background: 'rgba(18,18,16,.72)', backdropFilter: 'blur(6px)', color: dark, fontFamily: disp, fontSize: 12.5,
        padding: '8px 14px', borderRadius: 999, whiteSpace: 'nowrap', border: '1px solid rgba(255,255,255,.12)' }}>
        Spred klodserne ud på en ensfarvet flade
      </div>

      {/* drag overlay */}
      {drag && (
        <div style={{ position: 'absolute', inset: 16, border: '2px dashed var(--accent)', borderRadius: 18, zIndex: 70,
          display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(18,18,16,.6)',
          color: dark, fontFamily: disp, fontSize: 16 }}>
          Slip billedet for at analysere
        </div>
      )}

      {/* shutter row */}
      <div style={{ position: 'absolute', bottom: 40, left: 0, right: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-around' }}>
        <button onClick={() => fileRef.current && fileRef.current.click()}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: dark, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5 }}>
          <span style={{ width: 44, height: 44, borderRadius: 11, border: '1.5px solid rgba(255,255,255,.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18 }}>↑</span>
          <span style={{ fontFamily: mono, fontSize: 8.5, opacity: .8 }}>UPLOAD</span>
        </button>

        <button onClick={snap} disabled={status !== 'live'}
          style={{ background: 'none', border: 'none', cursor: status === 'live' ? 'pointer' : 'default', padding: 0, opacity: status === 'live' ? 1 : 0.4 }}>
          <span style={{ display: 'block', width: 78, height: 78, borderRadius: 42, border: '3px solid ' + dark, padding: 5, boxSizing: 'border-box' }}>
            <span style={{ display: 'block', width: '100%', height: '100%', borderRadius: 32, background: 'var(--accent)' }} />
          </span>
        </button>

        <div style={{ width: 44, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5, opacity: .35, color: dark }}>
          <span style={{ width: 44, height: 44, borderRadius: 22, border: '1.5px solid rgba(255,255,255,.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16 }}>⟳</span>
          <span style={{ fontFamily: mono, fontSize: 8.5 }}>VEND</span>
        </div>
      </div>

      <input ref={fileRef} type="file" accept="image/*" capture="environment" style={{ display: 'none' }}
        onChange={e => handleFile(e.target.files && e.target.files[0])} />

      {flash && <div style={{ position: 'absolute', inset: 0, background: '#fff', animation: 'flash .26s ease forwards', zIndex: 80 }} />}
    </div>
  );
}

// Analyzing: shows the captured photo + progress while the API call runs.
// `phase` text comes from the app; resolves when the parent advances.
function Analyzing({ photo, motion, error, onRetry, onUpload }) {
  const steps = ['Genkender former', 'Måler størrelser', 'Identificerer farver', 'Matcher mod database'];
  const [prog, setProg] = React.useState([0,0,0,0]);

  React.useEffect(() => {
    if (error) return;
    if (!motion) { setProg([90,90,90,90]); return; }
    let frame = 0;
    const id = setInterval(() => {
      frame += 1;
      // creep toward ~92% and wait for the real result to flip the screen
      setProg(prev => prev.map((v, i) => {
        const start = i * 10;
        return Math.max(0, Math.min(92, (frame - start) * 3.2));
      }));
    }, 45);
    return () => clearInterval(id);
  }, [motion, error]);

  return (
    <div style={{ position: 'absolute', inset: 0, background: T.screen, color: '#f7f5ee', padding: '54px 22px 22px', boxSizing: 'border-box' }}>
      <div style={{ fontFamily: mono, fontSize: 10.5, opacity: .7, letterSpacing: 1 }}>
        {error ? 'ANALYSE · FEJL' : 'ANALYSE · BEHANDLER FOTO'}
      </div>

      <div style={{ position: 'relative', marginTop: 14, height: 250, borderRadius: 14, overflow: 'hidden', border: '1px solid rgba(255,255,255,.12)', background: '#0e0d0a' }}>
        {photo && <img src={photo} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', opacity: .9 }} />}
        {!error && (
          <div style={{ position: 'absolute', left: 0, right: 0, height: 2, background: 'var(--accent)', boxShadow: '0 0 14px 2px var(--accent)',
            animation: motion ? 'scanline 1.6s ease-in-out infinite' : 'none', top: '50%' }} />
        )}
        <div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(217,119,87,.05) 1px, transparent 1px), linear-gradient(90deg, rgba(217,119,87,.05) 1px, transparent 1px)', backgroundSize: '20px 20px' }} />
      </div>

      {error ? (
        <div style={{ marginTop: 22 }}>
          <div style={{ fontFamily: disp, fontSize: 16, fontWeight: 600 }}>Kunne ikke læse klodserne</div>
          <div style={{ fontFamily: disp, fontSize: 13, opacity: .8, lineHeight: 1.5, marginTop: 6 }}>
            Prøv et tydeligere billede med god belysning og klodserne spredt ud.
          </div>
          <div style={{ display: 'flex', gap: 10, marginTop: 18 }}>
            <Btn kind="ghost" onClick={onUpload} style={{ color: '#f7f5ee', borderColor: 'rgba(255,255,255,.3)' }}>Upload billede</Btn>
            <Btn onClick={onRetry}>Prøv igen</Btn>
          </div>
        </div>
      ) : (
        <div style={{ marginTop: 20, display: 'flex', flexDirection: 'column', gap: 13 }}>
          {steps.map((s, i) => (
            <div key={s}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: mono, fontSize: 10.5, opacity: .85 }}>
                <span>{s}</span><span>{Math.round(prog[i])}%</span>
              </div>
              <div style={{ height: 5, borderRadius: 3, background: 'rgba(255,255,255,.1)', marginTop: 5, overflow: 'hidden' }}>
                <div style={{ width: prog[i] + '%', height: '100%', background: 'var(--accent)', transition: 'width .1s linear' }} />
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Camera, Analyzing });
