// public/scan.jsx — full-screen overlay used by employees for both check-in and check-out.
// Steps: scan QR → take selfie → confirm → submit (with GPS best-effort).

const { useEffect: useEffectS, useRef: useRefS, useState: useStateS } = React;

function ScanCheckin({ kind, empId, note, onCancel, onDone, onError }) {
  // step: 'scanning' | 'selfie' | 'confirm' | 'submitting'
  const [step, setStep] = useStateS('scanning');
  const [token, setToken] = useStateS(null);
  const [selfieBlob, setSelfieBlob] = useStateS(null);
  const [selfieUrl, setSelfieUrl] = useStateS(null);
  const [errMsg, setErrMsg] = useStateS(null);

  const videoRef = useRefS(null);
  const streamRef = useRefS(null);
  const scanRafRef = useRefS(0);
  const cancelledRef = useRefS(false);

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

  const startCamera = async (facingMode) => {
    stopStream();
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { facingMode },
      audio: false,
    });
    streamRef.current = stream;
    if (videoRef.current) {
      videoRef.current.srcObject = stream;
      await videoRef.current.play().catch(() => {});
    }
  };

  // ----- QR scanning loop (rear camera) -----
  useEffectS(() => {
    if (step !== 'scanning') return;
    let alive = true;
    (async () => {
      try {
        await startCamera({ ideal: 'environment' });
      } catch {
        if (!alive) return;
        setErrMsg('Cần cấp quyền camera để chấm công.');
        return;
      }
      const tick = () => {
        if (!alive || cancelledRef.current) return;
        const v = videoRef.current;
        if (v && v.readyState >= 2 && typeof jsQR === 'function') {
          const w = v.videoWidth, h = v.videoHeight;
          if (w && h) {
            const c = document.createElement('canvas');
            c.width = w; c.height = h;
            const ctx = c.getContext('2d', { willReadFrequently: true });
            ctx.drawImage(v, 0, 0, w, h);
            const data = ctx.getImageData(0, 0, w, h);
            const code = jsQR(data.data, w, h, { inversionAttempts: 'dontInvert' });
            if (code && code.data) {
              setToken(code.data);
              setStep('selfie');
              return;
            }
          }
        }
        scanRafRef.current = requestAnimationFrame(tick);
      };
      scanRafRef.current = requestAnimationFrame(tick);
    })();
    return () => { alive = false; cancelAnimationFrame(scanRafRef.current); };
  }, [step]);

  // ----- Selfie capture (front camera) -----
  useEffectS(() => {
    if (step !== 'selfie') return;
    let alive = true;
    (async () => {
      try {
        await startCamera({ ideal: 'user' });
      } catch {
        if (!alive) return;
        setErrMsg('Cần camera trước để chụp selfie.');
      }
    })();
    return () => { alive = false; stopStream(); };
  }, [step]);

  const snap = async () => {
    try {
      const blob = await compressSelfie(videoRef.current);
      setSelfieBlob(blob);
      setSelfieUrl(URL.createObjectURL(blob));
      stopStream();
      setStep('confirm');
    } catch (e) {
      setErrMsg('Không chụp được, thử lại.');
    }
  };

  const retake = () => {
    if (selfieUrl) URL.revokeObjectURL(selfieUrl);
    setSelfieBlob(null);
    setSelfieUrl(null);
    setErrMsg(null);
    setStep('selfie');
  };

  const submit = async () => {
    setStep('submitting');
    setErrMsg(null);
    const gps = await getGps(5000);
    const url = kind === 'checkin'
      ? '/api/timesheets/checkin'
      : '/api/timesheets/checkout';
    const fields = {
      empId,
      token,
      selfie: selfieBlob,
      gpsLat: gps ? gps.lat : null,
      gpsLng: gps ? gps.lng : null,
      gpsAccuracy: gps ? gps.accuracy : null,
    };
    if (kind === 'checkout' && note != null) fields.note = note;
    try {
      const result = await postMultipart(url, fields);
      cancelledRef.current = true;
      stopStream();
      if (selfieUrl) URL.revokeObjectURL(selfieUrl);
      onDone(result);
    } catch (e) {
      const code = e.body && e.body.error;
      const msg =
        code === 'qr_expired' ? 'Mã QR đã hết hạn (>30s), vui lòng scan lại.' :
        code === 'qr_replay'  ? 'Mã QR này đã dùng rồi, scan mã mới.' :
        code === 'qr_invalid' ? 'Mã QR không hợp lệ, scan lại.' :
        code === 'selfie_required'  ? 'Thiếu ảnh selfie.' :
        code === 'selfie_too_large' ? 'Ảnh quá lớn (>200KB).' :
        code === 'no_active_checkin' ? 'Bạn chưa check-in, không thể check-out.' :
        'Lỗi gửi, kiểm tra mạng và thử lại.';
      setErrMsg(msg);
      // Go back to scanning so user can rescan a fresh QR
      setStep('scanning');
      setToken(null);
      if (selfieUrl) URL.revokeObjectURL(selfieUrl);
      setSelfieBlob(null);
      setSelfieUrl(null);
    }
  };

  const close = () => {
    cancelledRef.current = true;
    stopStream();
    if (selfieUrl) URL.revokeObjectURL(selfieUrl);
    onCancel();
  };

  // Title
  const title = kind === 'checkin' ? 'Chấm công vào ca' : 'Chấm công kết ca';
  const stepLabel =
    step === 'scanning' ? '1/3 — Quét mã QR ở quầy' :
    step === 'selfie'   ? '2/3 — Chụp selfie' :
    step === 'confirm'  ? '3/3 — Xác nhận' :
    'Đang gửi…';

  return (
    <div className="scan-overlay">
      <div className="scan-bar">
        <button className="scan-x" onClick={close} aria-label="Đóng">✕</button>
        <div className="scan-title">
          <div>{title}</div>
          <div className="scan-step">{stepLabel}</div>
        </div>
      </div>

      <div className="scan-stage">
        {(step === 'scanning' || step === 'selfie') && (
          <video ref={videoRef} className="scan-video" playsInline muted />
        )}
        {step === 'scanning' && <div className="scan-viewfinder" />}
        {step === 'confirm' && selfieUrl && (
          <img src={selfieUrl} alt="selfie" className="scan-preview" />
        )}
        {step === 'submitting' && (
          <div className="scan-spinner-wrap"><div className="spinner" /></div>
        )}
        {errMsg && <div className="scan-error">{errMsg}</div>}
      </div>

      <div className="scan-foot">
        {step === 'scanning' && (
          <div className="scan-hint">
            Hướng camera vào mã QR trên màn hình quản lý. Mã đổi mỗi 30 giây.
          </div>
        )}
        {step === 'selfie' && (
          <button className="big-btn primary" onClick={snap}>Chụp selfie</button>
        )}
        {step === 'confirm' && (
          <>
            <button className="big-btn ghost" onClick={retake}>Chụp lại</button>
            <button className="big-btn primary" onClick={submit}>
              {kind === 'checkin' ? 'Gửi check-in' : 'Gửi check-out'}
            </button>
          </>
        )}
      </div>
    </div>
  );
}

window.ScanCheckin = ScanCheckin;
