const FaceScanCamera = ({ onComplete, onCancel, onError }) => {
  const videoRef = React.useRef(null);
  const svgRef = React.useRef(null);
  const streamRef = React.useRef(null);
  const cancelledRef = React.useRef(false);
  const [status, setStatus] = React.useState('Загрузка моделей…');

  React.useEffect(() => {
    cancelledRef.current = false;
    let scan = null;

    const REQUIRED_FRAMES = 5;
    const TIMEOUT_MS = 30000;

    const run = async () => {
      try {
        await loadFaceModels();
        if (cancelledRef.current) return;
        setStatus('Запуск камеры…');
        streamRef.current = await startCamera(videoRef.current);
        if (cancelledRef.current) return;
        scan = createFaceScan(svgRef.current);
        setStatus('Смотрите прямо в камеру…');

        const descriptors = [];
        const deadline = performance.now() + TIMEOUT_MS;
        while (true) {
          if (cancelledRef.current) return;
          if (performance.now() > deadline) throw new Error('timeout');
          if (scan.isComplete && descriptors.length >= REQUIRED_FRAMES) break;

          const result = await detectWithDescriptor(videoRef.current);
          if (cancelledRef.current) return;
          if (!result) {
            setStatus('Не вижу лица…');
            await new Promise((r) => requestAnimationFrame(r));
            continue;
          }
          const yaw = yawOffset(result.landmarks);
          const pr = pitchRatio(result.landmarks);
          scan.update(yaw, pr);
          if (
            scan.isCenter(yaw, pr) &&
            descriptors.length < REQUIRED_FRAMES &&
            result.detection.score > 0.5
          ) {
            descriptors.push(Array.from(result.descriptor));
          }
          setStatus(
            scan.warmed
              ? `Секторы: ${scan.count}/${scan.total} · кадры: ${descriptors.length}/${REQUIRED_FRAMES}`
              : 'Смотрите прямо в камеру…'
          );
          await new Promise((r) => requestAnimationFrame(r));
        }
        if (cancelledRef.current) return;
        const out = new Array(128).fill(0);
        for (const d of descriptors) for (let i = 0; i < 128; i++) out[i] += d[i];
        for (let i = 0; i < 128; i++) out[i] /= descriptors.length;
        onComplete(out);
      } catch (e) {
        if (cancelledRef.current) return;
        if (e && e.message === 'timeout') {
          onError('Не удалось завершить скан. Медленно проведите взглядом по кругу.');
        } else {
          onError('Ошибка: ' + (e && e.message ? e.message : String(e)));
        }
      }
    };

    run();

    return () => {
      cancelledRef.current = true;
      stopCamera(streamRef.current);
      streamRef.current = null;
    };
  }, []);

  return (
    <div style={{ display:'flex', flexDirection:'column', gap: 12 }}>
      <div style={{ position:'relative', width:'100%', aspectRatio: '4 / 3', background:'#000', borderRadius: 14, overflow:'hidden' }}>
        <video ref={videoRef} autoPlay muted playsInline
               style={{ position:'absolute', inset: 0, width:'100%', height:'100%', objectFit:'cover' }}/>
        <svg ref={svgRef} style={{ position:'absolute', inset: 0, width:'100%', height:'100%', pointerEvents:'none', transform:'scaleX(-1)' }}/>
      </div>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap: 10 }}>
        <div style={{ fontSize: 13, color:'var(--fg-muted)' }}>{status}</div>
        {onCancel && (
          <Button variant="ghost" size="sm" onClick={onCancel}>Отмена</Button>
        )}
      </div>
    </div>
  );
};

Object.assign(window, { FaceScanCamera });
