// InsuranceCapture.jsx — Scan / Speak / Type tabs to capture insurance info.
// Scan → POST /api/scan-insurance (OCR cascade: Azure DI → Google Vision → Claude benefits → Tesseract).
// Speak → CA §632 consent gate → browser SpeechRecognition (no backend needed);
//         falls back to MediaRecorder → POST /api/transcribe if unavailable.
// Type → traditional text inputs.
// After scan: shows InsuranceAnalyzer (patient explainer + office pricing breakdown).
// Emits onChange({carrier, plan, memberId, groupId, ...fullParsed}) to the parent.
const { useState: useICs, useRef: useICr } = React;

function InsuranceCapture({ value = {}, onChange, showAnalyzer = true, analyzerMode = 'patient' }) {
  const [tab, setTab] = useICs('scan');
  const [scanLoading, setScanLoading] = useICs(false);
  const [scanErr, setScanErr] = useICs(null);
  const [scanMeta, setScanMeta] = useICs(null); // confidence, hitl_status, disclaimer from API
  const [fullParsed, setFullParsed] = useICs(null); // full parsed object for analyzer
  const [analyzerOpen, setAnalyzerOpen] = useICs(false);
  const [sttErr, setSttErr] = useICs(null);
  const [recording, setRecording] = useICs(false);
  const [sttStatus, setSttStatus] = useICs(''); // 'listening' | 'processing' | ''
  const [consentOk, setConsentOk] = useICs(() => {
    try { return !!localStorage.getItem('td_voice_consent'); } catch { return false; }
  });
  const mediaRef = useICr(null);
  const chunksRef = useICr([]);
  const recognitionRef = useICr(null);

  const update = (patch) => onChange && onChange({ ...value, ...patch });

  // ── Scan ──────────────────────────────────────────────────────────────────
  const onScanFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    setScanLoading(true); setScanErr(null); setScanMeta(null);
    try {
      const fd = new FormData();
      fd.append('image', file);
      const resp = await fetch('/api/scan-insurance', { method: 'POST', body: fd });
      const d = await resp.json().catch(() => ({}));
      if (!resp.ok || d.ok === false) {
        setScanErr(d.error || "We couldn't read your card. Please try again or enter your details manually.");
        setFullParsed(null);
        return;
      }
      const p = d.parsed || d;
      if (!p.carrier && !p.member_id && !p.group_id) {
        setScanErr('Card scanned but no fields were recognised. Please type the details below.');
        return;
      }
      const conf = typeof d.confidence === 'number' ? d.confidence : null;
      setScanMeta({
        confidence: conf,
        ocr_source: d.ocr_source || d.source || null,
        hitl_status: d.hitl_status || (d.requires_review ? 'PENDING_HITL_REVIEW' : null),
        disclaimer: d.disclaimer || 'AI-extracted information. Verify benefits with your insurer before treatment. Not a guarantee of coverage.',
        requires_review: !!d.requires_review,
      });
      setFullParsed(p);
      setAnalyzerOpen(true);
      update({
        carrier:  p.carrier   || value.carrier  || '',
        plan:     p.plan_type || p.plan         || value.plan    || '',
        memberId: p.member_id || p.memberId     || value.memberId || '',
        groupId:  p.group_id  || p.groupId      || value.groupId  || '',
        _scan_source: d.ocr_source || d.source,
        _scan_notes:  p.notes || p.note || '',
        _parsed: p,
        _scan_confidence: conf,
        _hitl_status: d.hitl_status,
      });
    } catch {
      setScanErr('Network error scanning card. Please try again or type it in.');
    } finally {
      setScanLoading(false);
    }
  };

  const confidenceBadge = (conf) => {
    if (conf == null || Number.isNaN(conf)) return null;
    const pct = conf > 1 ? Math.round(conf) : Math.round(conf * 100);
    if (pct >= 97) {
      return { label: `${pct}% confidence`, color: 'var(--td-success)', bg: 'var(--td-success-light)' };
    }
    if (pct >= 70) {
      return { label: `${pct}% confidence`, color: 'var(--td-warning)', bg: 'var(--td-warning-light)' };
    }
    return { label: `${pct}% confidence — MANUAL REVIEW NEEDED`, color: 'var(--td-danger)', bg: 'var(--td-danger-light)' };
  };

  // ── STT helpers ───────────────────────────────────────────────────────────
  const parseTranscript = (text) => {
    const t = text || '';
    const carrierRx = /delta|aetna|cigna|metlife|blue\s*cross|blue\s*shield|united\s*health(?:care)?|kaiser|guardian|humana|premera|dentaquest|denti-?cal|medicaid|sunlife|principal|ameritas|careington/i;
    const memberRx  = /member(?:\s*id)?[:\s#]*([\w-]+)/i;
    const groupRx   = /group(?:\s*(?:id|number))?[:\s#]*([\w-]+)/i;
    const planRx    = /\b(ppo|hmo|dhmo|epo|indemnity|medicaid|medicare)\b/i;
    const carrierM  = carrierRx.exec(t);
    const memberM   = memberRx.exec(t);
    const groupM    = groupRx.exec(t);
    const planM     = planRx.exec(t);
    update({
      carrier:  carrierM ? carrierM[0].trim() : value.carrier  || '',
      plan:     planM    ? planM[1].toUpperCase() : value.plan  || '',
      memberId: memberM  ? memberM[1]  : value.memberId || '',
      groupId:  groupM   ? groupM[1]   : value.groupId  || '',
      _transcript: t,
    });
  };

  const grantConsent = () => {
    const ok = window.confirm(
      'California Penal Code § 632 consent\n\n' +
      'We’ll transcribe your spoken insurance details using your browser’s speech recognition. ' +
      'Audio is processed locally in your browser and not sent to our servers. ' +
      'Press OK to consent and continue.'
    );
    if (!ok) return false;
    try { localStorage.setItem('td_voice_consent', new Date().toISOString()); } catch {}
    setConsentOk(true);
    return true;
  };

  // Primary: browser Web Speech API (Chrome/Edge — no backend needed)
  const startBrowserSTT = () => {
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    const rec = new SpeechRecognition();
    recognitionRef.current = rec;
    rec.continuous = false;
    rec.lang = 'en-US';
    rec.interimResults = false;
    rec.maxAlternatives = 1;

    rec.onstart  = () => { setRecording(true); setSttStatus('listening'); setSttErr(null); };
    rec.onend    = () => { setRecording(false); setSttStatus(''); };
    rec.onerror  = (ev) => {
      setRecording(false); setSttStatus('');
      if (ev.error === 'not-allowed') setSttErr('Microphone access denied. Type it in instead.');
      else if (ev.error === 'no-speech') setSttErr('Nothing heard. Try again or type it in.');
      else setSttErr(`Recognition error: ${ev.error}. Type it in instead.`);
    };
    rec.onresult = (ev) => {
      const text = ev.results[0][0].transcript;
      parseTranscript(text);
    };
    rec.start();
  };

  // Fallback: MediaRecorder → POST /api/transcribe
  const startFallbackSTT = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const mr = new MediaRecorder(stream);
      mediaRef.current = mr;
      chunksRef.current = [];
      mr.ondataavailable = (e) => { if (e.data && e.data.size) chunksRef.current.push(e.data); };
      mr.onstop = async () => {
        stream.getTracks().forEach(t => t.stop());
        setSttStatus('processing');
        try {
          const blob = new Blob(chunksRef.current, { type: 'audio/webm' });
          const fd = new FormData();
          fd.append('audio', blob, 'insurance.webm');
          const resp = await fetch('/api/transcribe', { method: 'POST', body: fd });
          const d = await resp.json().catch(() => ({}));
          if (!resp.ok || d.ok === false) {
            setSttErr(d.error || 'Transcription failed. Please type it in.');
          } else if (d.text) {
            parseTranscript(d.text);
          } else {
            setSttErr('Nothing heard. Try again or type it in.');
          }
        } catch {
          setSttErr('Network error during transcription. Type it in instead.');
        } finally {
          setSttStatus('');
          setRecording(false);
        }
      };
      mr.start();
      setRecording(true);
      setSttStatus('listening');
      setSttErr(null);
      // Auto-stop after 15 s
      setTimeout(() => {
        if (mr.state === 'recording') { mr.stop(); setRecording(false); }
      }, 15000);
    } catch {
      setSttErr('Microphone access denied. Type it in instead.');
      setRecording(false); setSttStatus('');
    }
  };

  const consentAndRecord = async () => {
    if (!consentOk && !grantConsent()) return;
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (SpeechRecognition) {
      startBrowserSTT();
    } else {
      await startFallbackSTT();
    }
  };

  const stopRecording = () => {
    if (recognitionRef.current) { recognitionRef.current.stop(); recognitionRef.current = null; }
    if (mediaRef.current && mediaRef.current.state === 'recording') mediaRef.current.stop();
    setRecording(false); setSttStatus('');
  };

  // ── Render ────────────────────────────────────────────────────────────────
  const TABS = [['scan', 'Scan card'], ['speak', 'Speak'], ['type', 'Type']];

  return (
    <div className="td-card" style={{ padding: 0, overflow: 'hidden' }}>
      <div role="tablist" aria-label="Insurance capture method"
        style={{ display:'flex', borderBottom:'1px solid var(--ink-5)' }}>
        {TABS.map(([k, label]) => (
          <button key={k} role="tab" aria-selected={tab===k}
            onClick={()=>{ setTab(k); setScanErr(null); setSttErr(null); }}
            style={{
              flex:1, padding:'10px 12px', fontSize:13, fontWeight:600, cursor:'pointer',
              background: tab===k ? 'var(--bone)' : 'var(--paper)',
              color: tab===k ? 'var(--ink-1)' : 'var(--ink-3)',
              border:0, borderBottom: tab===k ? '2px solid var(--seal)' : '2px solid transparent',
            }}>{label}</button>
        ))}
      </div>

      <div style={{ padding:'var(--s-4)' }}>
        {tab === 'scan' && (
          <div>
            <p style={{margin:'0 0 var(--s-3)',fontSize:13,color:'var(--ink-2)'}}>
              Take a photo of the front of your insurance card. The image is processed server-side only and not retained.
            </p>
            {scanLoading ? (
              <div aria-busy="true" aria-label="Reading insurance card" style={{ marginBottom: 'var(--s-3)' }}>
                <div className="td-skeleton" style={{ height: 14, width: '70%', marginBottom: 8 }} />
                <div className="td-skeleton" style={{ height: 14, width: '55%', marginBottom: 8 }} />
                <div className="td-skeleton" style={{ height: 14, width: '62%' }} />
                <p style={{ marginTop: 10, fontSize: 13, color: 'var(--td-text-muted)' }}>Reading card…</p>
              </div>
            ) : (
              <label className="td-btn td-btn-secondary td-btn-md" style={{display:'inline-block',cursor:'pointer'}}>
                <input type="file" accept="image/*" capture="environment" onChange={onScanFile}
                  style={{position:'absolute',width:1,height:1,opacity:0}}/>
                Take or upload a photo
              </label>
            )}
            {scanErr && (
              <div role="alert" className="td-body-sm" style={{marginTop:8,color:'var(--td-danger)',padding:'8px 10px',background:'var(--td-danger-light)',borderRadius:8}}>
                {scanErr}
              </div>
            )}
            {(fullParsed || value._parsed) && !scanLoading && (
              <div className="td-card td-card-sm" style={{ marginTop: 'var(--s-3)' }}>
                {(() => {
                  const conf = scanMeta?.confidence ?? value._scan_confidence;
                  const badge = confidenceBadge(conf);
                  const disclaimer = scanMeta?.disclaimer
                    || 'AI-extracted information. Verify benefits with your insurer before treatment. Not a guarantee of coverage.';
                  const hitl = scanMeta?.hitl_status || value._hitl_status;
                  return (
                    <>
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', marginBottom: 8 }}>
                        {(scanMeta?.ocr_source || value._scan_source) && (
                          <span style={{
                            fontSize: 11, fontWeight: 600, padding: '3px 8px', borderRadius: 6,
                            background: 'var(--paper)', color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.04em',
                          }}>
                            OCR: {String(scanMeta?.ocr_source || value._scan_source).replace(/_/g, ' ')}
                          </span>
                        )}
                        {badge && (
                          <span style={{
                            display: 'inline-block', fontSize: 12, fontWeight: 700,
                            padding: '4px 10px', borderRadius: 999,
                            color: badge.color, background: badge.bg,
                          }}>
                            {badge.label}
                          </span>
                        )}
                      </div>
                      <p style={{ margin: '0 0 8px', fontSize: 13, fontStyle: 'italic', color: 'var(--td-text-muted)' }}>
                        {disclaimer}
                      </p>
                      {hitl === 'PENDING_HITL_REVIEW' && (
                        <p style={{ margin: 0, fontSize: 13, color: 'var(--ink-2)' }}>
                          Our team is reviewing your card for accuracy (usually &lt; 2 hours).
                        </p>
                      )}
                    </>
                  );
                })()}
              </div>
            )}
            {value._scan_notes && (
              <div style={{marginTop:8,fontSize:12,color:'var(--ink-3)',padding:'6px 8px',background:'var(--bone)',borderRadius:6}}>
                {value._scan_notes}
              </div>
            )}
          </div>
        )}

        {tab === 'speak' && (
          <div>
            <p style={{margin:'0 0 var(--s-3)',fontSize:13,color:'var(--ink-2)'}}>
              Say your carrier name, plan type, member ID, and group ID. Speak clearly and pause between items.
            </p>
            {!recording && sttStatus !== 'processing' ? (
              <button type="button" className="td-btn td-btn-secondary td-btn-md" onClick={consentAndRecord}>
                {consentOk ? 'Start recording' : 'Consent + start recording'}
              </button>
            ) : sttStatus === 'processing' ? (
              <div style={{fontSize:13,color:'var(--td-text-muted)',padding:'8px 0'}}>Transcribing…</div>
            ) : (
              <button type="button" className="td-btn td-btn-primary td-btn-md" onClick={stopRecording}>
                ■ Stop recording
              </button>
            )}
            {recording && sttStatus === 'listening' && (
              <div style={{marginTop:8,fontSize:13,color:'var(--seal)',display:'flex',alignItems:'center',gap:6}}>
                <span style={{width:8,height:8,borderRadius:'50%',background:'var(--seal)',display:'inline-block',animation:'pulse 1s ease-in-out infinite'}}/>
                Listening… speak now
              </div>
            )}
            {sttErr && (
              <div role="alert" className="td-body-sm" style={{marginTop:8,color:'var(--td-danger)',padding:'8px 10px',background:'var(--td-danger-light)',borderRadius:8}}>
                {sttErr}
              </div>
            )}
            {value._transcript && (
              <div style={{marginTop:'var(--s-2)',padding:'8px 10px',background:'var(--bone)',borderRadius:8,fontSize:13,color:'var(--ink-2)'}}>
                <strong>Heard:</strong> "{value._transcript}"
              </div>
            )}
          </div>
        )}

        {tab === 'type' && (
          <p style={{margin:'0 0 var(--s-3)',fontSize:13,color:'var(--ink-2)'}}>
            Enter your insurance details below.
          </p>
        )}

        <div style={{display:'grid',gridTemplateColumns:'repeat(2, 1fr)',gap:'var(--s-3)',marginTop:'var(--s-3)'}}>
          <Field label="Carrier" value={value.carrier} onChange={v=>update({carrier:v})} placeholder="Delta Dental PPO"/>
          <Field label="Plan type" value={value.plan} onChange={v=>update({plan:v})} placeholder="PPO"/>
          <Field label="Member ID" value={value.memberId} onChange={v=>update({memberId:v})} placeholder="ABC1234567"/>
          <Field label="Group ID" value={value.groupId} onChange={v=>update({groupId:v})} placeholder="0001234"/>
        </div>
      </div>

      {/* ── Insurance Analyzer ──────────────────────────────────────────── */}
      {showAnalyzer && (fullParsed || value._parsed) && (
        <div style={{borderTop:'1px solid var(--ink-5,#1f2b36)'}}>
          <button
            onClick={() => setAnalyzerOpen(o => !o)}
            style={{width:'100%',padding:'12px 16px',background:'transparent',border:'none',cursor:'pointer',
              display:'flex',alignItems:'center',justifyContent:'space-between',
              color:'var(--ink-2,#8b9aa7)',fontSize:13,fontWeight:700}}>
            <span style={{display:'inline-flex',alignItems:'center',gap:6}}>
              {window.FlatIcon && React.createElement(window.FlatIcon, { name: 'chart', size: 14, color: 'var(--ink-2)' })}
              Coverage Analyzer {analyzerMode === 'office' ? '— Office View' : '— Patient View'}
            </span>
            <span style={{fontSize:12}}>{analyzerOpen ? '▲ hide' : '▼ show'}</span>
          </button>
          {analyzerOpen && window.InsuranceAnalyzer && (
            <div style={{padding:'0 var(--s-4,16px) var(--s-4,16px)'}}>
              <window.InsuranceAnalyzer
                insurance={fullParsed || value._parsed}
                defaultMode={analyzerMode}/>
            </div>
          )}
          {analyzerOpen && !window.InsuranceAnalyzer && (
            <div style={{padding:16,fontSize:12,color:'var(--ink-3,#8b9aa7)'}}>
              Load InsuranceAnalyzer.jsx to see coverage details.
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function Field({ label, value, onChange, placeholder }) {
  return (
    <label className="td-label" style={{display:'flex',flexDirection:'column',gap:4,fontWeight:600,textTransform:'none',letterSpacing:'normal',color:'var(--td-text-secondary)'}}>
      {label}
      <input type="text" className="td-input" value={value || ''} onChange={(e)=>onChange(e.target.value)} placeholder={placeholder}/>
    </label>
  );
}

window.InsuranceCapture = InsuranceCapture;
