import React, { useState, useCallback, useRef } from 'react';
import { BarcodeScanner, BarcodeFormat } from '@capacitor-mlkit/barcode-scanning';
import { Capacitor } from '@capacitor/core';
import 'barcode-detector/polyfill';
import './ScannerView.css';

const CIP_REGEX = /^[A-Z0-9]{16}$/i;

function playBeep() {
  try {
    const ctx = new (window.AudioContext || window.webkitAudioContext)();
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = 'sine';
    osc.frequency.setValueAtTime(1046, ctx.currentTime);
    osc.frequency.exponentialRampToValueAtTime(1318, ctx.currentTime + 0.08);
    gain.gain.setValueAtTime(0.28, ctx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.35);
    osc.connect(gain);
    gain.connect(ctx.destination);
    osc.start();
    osc.stop(ctx.currentTime + 0.38);
  } catch (_) { /* No audio context available */ }
}

function ScannerView({ onClose, onSelectMedicine }) {
  const videoRef = useRef(null);
  const streamRef = useRef(null);
  const rafRef = useRef(null);
  const detectorRef = useRef(null);

  const [phase, setPhase] = useState('idle');
  const [manualCip, setManualCip] = useState('');
  const [prescriptions, setPrescriptions] = useState([]);
  const [scannedCip, setScannedCip] = useState(null);
  const [loadingPrescriptions, setLoadingPrescriptions] = useState(false);
  const [errorMsg, setErrorMsg] = useState('');

  const isNative = Capacitor.isNativePlatform();

  const fetchPrescriptions = useCallback(async (cip) => {
    setLoadingPrescriptions(true);
    try {
      const res = await fetch(`/api/tsi/${encodeURIComponent(cip)}/prescriptions`);
      const data = await res.json();
      setPrescriptions(data);
    } catch {
      setPrescriptions([]);
    } finally {
      setLoadingPrescriptions(false);
    }
  }, []);

  function stopCamera() {
    streamRef.current?.getTracks().forEach(t => t.stop());
    streamRef.current = null;
    if (rafRef.current) {
      cancelAnimationFrame(rafRef.current);
      rafRef.current = null;
    }
  }

  async function handleNativeScan() {
    setErrorMsg('');
    try {
      const supported = await BarcodeScanner.isSupported();
      if (!supported) {
        setErrorMsg('Barcode scanning is not supported on this device.');
        setPhase('error');
        return;
      }

      const permission = await BarcodeScanner.checkPermissions();
      if (permission.camera !== 'granted') {
        const request = await BarcodeScanner.requestPermissions();
        if (request.camera !== 'granted') {
          setErrorMsg('Camera permission denied. Please enable it in settings, or enter your CIP code manually.');
          setPhase('error');
          return;
        }
      }

      setPhase('scanning');

      const result = await BarcodeScanner.scan({
        formats: [BarcodeFormat.PDF417, BarcodeFormat.Code128, BarcodeFormat.QrCode],
        autoZoom: true,
      });

      const barcode = result.barcodes[0];
      const rawValue = barcode?.rawValue;

      if (!rawValue || !CIP_REGEX.test(rawValue)) {
        setErrorMsg('Invalid card barcode. Please try again or enter your CIP code manually.');
        setPhase('error');
        return;
      }

      playBeep();
      setScannedCip(rawValue);
      setPhase('prescriptions');
      fetchPrescriptions(rawValue);
    } catch (err) {
      if (err?.message?.includes('cancel') || err?.message?.includes('User')) {
        setPhase('idle');
        return;
      }
      setErrorMsg(`Scan failed: ${err.message || 'Unknown error'}`);
      setPhase('error');
    }
  }

  async function handleWebScan() {
    setErrorMsg('');
    try {
      if (!navigator.mediaDevices?.getUserMedia) {
        setErrorMsg('Camera not available in this browser.');
        setPhase('error');
        return;
      }

      let detector;
      try {
        detector = new BarcodeDetector({ formats: ['pdf417', 'code_128', 'qr_code'] });
      } catch {
        setErrorMsg('Barcode detection is not supported in this browser.');
        setPhase('error');
        return;
      }

      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: { ideal: 'environment' }, width: { ideal: 1280 }, height: { ideal: 720 } },
      });

      streamRef.current = stream;
      detectorRef.current = detector;
      setPhase('scanning');

      await new Promise((resolve) => {
        requestAnimationFrame(() => {
          if (videoRef.current) {
            videoRef.current.srcObject = stream;
            videoRef.current.play().then(resolve).catch(resolve);
          } else {
            resolve();
          }
        });
      });

      let found = false;
      async function scanFrame() {
        if (found || !videoRef.current || !detectorRef.current) return;
        try {
          const barcodes = await detectorRef.current.detect(videoRef.current);
          if (barcodes.length > 0) {
            const rawValue = barcodes[0].rawValue;
            if (rawValue && CIP_REGEX.test(rawValue)) {
              found = true;
              stopCamera();
              playBeep();
              setScannedCip(rawValue);
              setPhase('prescriptions');
              fetchPrescriptions(rawValue);
              return;
            }
          }
        } catch { /* detector not ready */ }
        if (!found) {
          rafRef.current = requestAnimationFrame(scanFrame);
        }
      }
      scanFrame();
    } catch (err) {
      stopCamera();
      if (err.name === 'NotAllowedError') {
        setErrorMsg('Camera permission denied. Please allow camera access and try again.');
      } else if (err.name === 'NotFoundError') {
        setErrorMsg('No camera detected. Enter your CIP code manually.');
      } else {
        setErrorMsg(`Camera error: ${err.message || 'Unknown error'}`);
      }
      setPhase('error');
    }
  }

  function handleStartScan() {
    if (isNative) {
      handleNativeScan();
    } else {
      handleWebScan();
    }
  }

  function handleManualSubmit(e) {
    e.preventDefault();
    const cip = manualCip.trim();
    if (!cip) {
      setErrorMsg('Please enter a CIP code.');
      setPhase('error');
      return;
    }
    if (!CIP_REGEX.test(cip)) {
      setErrorMsg('Invalid CIP format. Must be 16 alphanumeric characters.');
      setPhase('error');
      return;
    }
    playBeep();
    setScannedCip(cip);
    setPhase('prescriptions');
    fetchPrescriptions(cip);
  }

  function handlePickPrescription(rx) {
    stopCamera();
    onSelectMedicine(rx.name);
  }

  function handleBack() {
    stopCamera();
    if (phase === 'prescriptions') {
      setPhase('idle');
      setPrescriptions([]);
      setScannedCip(null);
    } else {
      onClose();
    }
  }

  return (
    <div className="scanner-overlay">
      <div className="scanner-topbar">
        <button className="scanner-back-btn" onClick={handleBack} aria-label="Back">
          ← Back
        </button>
        <h2 className="scanner-title">
          {phase === 'prescriptions' ? '✅ TSI Scanned' : '📷 Scan TSI Card'}
        </h2>
        <span />
      </div>

      {/* ── Idle / Error / Scanning state ────────────────── */}
      {phase !== 'prescriptions' && (
        <div className="scanner-content">
          {phase === 'error' && (
            <div className="scan-error-panel">
              <span className="scan-error-icon">🚫</span>
              <p className="scan-error-msg">{errorMsg}</p>
              <button className="scan-retry-btn" onClick={() => { setErrorMsg(''); setPhase('idle'); }}>
                Try Again
              </button>
            </div>
          )}

          {phase === 'scanning' && !isNative && (
            <div className="scanner-camera-container">
              <video ref={videoRef} className="scanner-video" autoPlay muted playsInline />
              <div className="scanner-frame">
                <div className="corner tl" />
                <div className="corner tr" />
                <div className="corner bl" />
                <div className="corner br" />
              </div>
              <p className="scanner-hint">Point at barcode — hold steady</p>
            </div>
          )}

          {phase === 'scanning' && isNative && (
            <div className="scan-active-panel">
              <div className="scanner-spinner" />
              <p>Opening camera… Point at barcode</p>
            </div>
          )}

          {phase === 'idle' && (
            <button className="scan-start-btn" onClick={handleStartScan}>
              <span className="scan-start-icon">📷</span>
              {isNative ? 'Start Scanning' : 'Open Camera to Scan'}
            </button>
          )}

          <form className="manual-cip-section" onSubmit={handleManualSubmit}>
            <label className="cip-label" htmlFor="cip-input">Or enter CIP manually</label>
            <div className="cip-input-group">
              <input
                id="cip-input"
                className="cip-input"
                type="text"
                placeholder="Enter CIP code manually"
                value={manualCip}
                onChange={(e) => setManualCip(e.target.value)}
                maxLength={16}
                autoComplete="off"
                spellCheck={false}
              />
              <button type="submit" className="cip-submit-btn">Submit</button>
            </div>
          </form>
        </div>
      )}

      {/* ── Prescriptions result panel ───────────────────── */}
      {phase === 'prescriptions' && (
        <div className="scanner-prescriptions">
          <div className="scanned-card-info">
            <span className="scanned-icon">💳</span>
            <div>
              <p className="scanned-cip">{scannedCip}</p>
            </div>
          </div>

          <h3 className="rx-heading">Active Prescriptions</h3>
          <p className="rx-subheading">Tap a medicine to check availability at nearby pharmacies.</p>

          {loadingPrescriptions && (
            <div className="rx-loading">
              <div className="scanner-spinner" />
              <p>Loading prescriptions…</p>
            </div>
          )}

          {!loadingPrescriptions && prescriptions.length === 0 && (
            <p className="rx-empty">No active prescriptions found for this card.</p>
          )}

          <ul className="rx-list">
            {prescriptions.map((rx, i) => (
              <li key={i}>
                <button className="rx-item" onClick={() => handlePickPrescription(rx)}>
                  <div className="rx-item-info">
                    <span className="rx-name">{rx.name}</span>
                    <span className="rx-detail">{rx.dosage} · {rx.form}</span>
                    {rx.active_ingredient && (
                      <span className="rx-ingredient">{rx.active_ingredient}</span>
                    )}
                  </div>
                  <span className="rx-arrow">→</span>
                </button>
              </li>
            ))}
          </ul>

          <button className="scan-again-btn" onClick={() => {
            stopCamera();
            setPhase('idle');
            setPrescriptions([]);
            setScannedCip(null);
          }}>
            🔄 Scan Again
          </button>
        </div>
      )}
    </div>
  );
}

export default ScannerView;
