// Fill by Flow — main app.
// Voice: Gemini Live -> fill-query edge function -> spoken answer + on-screen result.
const { useState: useStA, useEffect: useEfA, useRef: useRfA, useCallback: useCbA } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "electric",
  "density": "medium",
  "units": "us",
  "layout": "dense",
  "screen": "listen"
}/*EDITMODE-END*/;

const SYSTEM_LABELS = {
  engine_oil: 'ENGINE OIL',
  coolant: 'COOLANT',
  brake: 'BRAKE FLUID',
  power_steering: 'POWER STEER',
  transmission_auto: 'AUTO TRANS',
  transmission_manual: 'MANUAL TRANS',
  transfer_case: 'TRANSFER CASE',
  front_diff: 'FRONT DIFF',
  rear_diff: 'REAR DIFF',
  washer: 'WASHER FLUID',
  ac_refrigerant: 'A/C REFRIGERANT',
  clutch: 'CLUTCH FLUID',
  dct: 'DCT FLUID',
  cvt: 'CVT FLUID',
  other: 'FLUID',
};

function labelForSystem(st) {
  return SYSTEM_LABELS[st] || (st ? st.replace(/_/g, ' ').toUpperCase() : 'FLUID');
}

function buildTranscript(args) {
  if (!args) return '';
  const parts = [args.year, args.make, args.model, args.engine_hint].filter(Boolean).map(String);
  const sys = args.system_hint ? labelForSystem(args.system_hint).toLowerCase() : '';
  return [parts.join(' '), sys].filter(Boolean).join(' · ');
}

function summarizeEngine(engine) {
  if (!engine) return '';
  // "5.0L EngineAutomatic" -> "5.0L"
  const m = /(\d+(?:\.\d+)?l)/i.exec(engine);
  const disp = m ? m[1].toUpperCase() : '';
  const rest = engine.replace(/engine|automatic|transmission|4x4|4wd/gi, '').replace(/\s+/g, ' ').trim();
  return disp ? (disp + (rest && !rest.toLowerCase().startsWith(disp.toLowerCase()) ? ' ' + rest : '')).trim() : engine;
}

function vehicleToVeh(vehicle, fallbackYear) {
  if (!vehicle) return { year: fallbackYear || '', make: '—', model: '', engine: '', trim: '' };
  return {
    year: vehicle.year ?? fallbackYear ?? '',
    make: (vehicle.make || '').toUpperCase(),
    model: vehicle.model || '',
    engine: summarizeEngine(vehicle.engine || ''),
    trim: '',
  };
}

function resultToCapacity(response, args) {
  const r = response.result || {};
  const primary = r.capacity && r.capacity.primary ? r.capacity.primary : {};
  const secondary = r.capacity && r.capacity.secondary ? r.capacity.secondary : {};
  const valueQ = typeof primary.value === 'number' ? primary.value : null;
  const valueL = typeof secondary.value === 'number' ? secondary.value : null;
  const noteParts = [];
  if (r.fluid_type) noteParts.push(r.fluid_type);
  if (r.fluid_spec && r.fluid_spec !== r.fluid_type) noteParts.push(r.fluid_spec);
  if (r.notes) noteParts.push(r.notes);
  return {
    kind: 'capacity',
    component: labelForSystem(r.system_type),
    query: buildTranscript(args) || (r.system_type || '').replace(/_/g, ' '),
    capacity: {
      value: valueQ != null ? valueQ : 0,
      units: 'QT',
      metric: valueL != null ? valueL : (valueQ != null ? +(valueQ * 0.946353).toFixed(2) : 0),
    },
    note: noteParts.filter(Boolean).join(' · ') || '—',
    source: r.source || 'Flow DB',
    confidence: r.confidence || null,
  };
}

function resultToJob(response, args) {
  const r = response.result || {};
  const vehicle = r.vehicle || {};
  const fluids = Array.isArray(r.fluids) ? r.fluids : [];
  const items = fluids.map((f) => {
    const primary = f.capacity && f.capacity.primary ? f.capacity.primary : {};
    const q = typeof primary.value === 'number' ? primary.value : null;
    return {
      id: f.spec_id || (f.system_type + '-' + Math.random().toString(36).slice(2, 7)),
      category: f.system_type.includes('diff') || f.system_type === 'transfer_case' || f.system_type.startsWith('transmission') ? 'DRIVELINE'
        : f.system_type === 'brake' ? 'BRAKES'
        : f.system_type === 'coolant' ? 'COOLING'
        : f.system_type === 'engine_oil' ? 'ENGINE'
        : f.system_type === 'power_steering' ? 'STEERING'
        : 'OTHER',
      name: labelForSystem(f.system_type),
      capacity: q,
      units: 'QT',
      spec: f.fluid_type || f.fluid_spec || '—',
      specDetail: [f.oem_part_number, f.fluid_spec].filter(Boolean).join(' · '),
      warning: null,
      flags: f.confidence ? [f.confidence.toUpperCase()] : [],
      procedure: f.notes || '',
    };
  });
  return {
    kind: 'job',
    jobName: 'FULL FLUID OVERVIEW',
    items,
  };
}

function responseToVeh(response, parsedArgs) {
  const r = response.result || {};
  return vehicleToVeh(r.vehicle, parsedArgs && parsedArgs.year);
}

function App() {
  const [tweaks, setTweaks] = useStA(() => {
    try {
      const saved = JSON.parse(localStorage.getItem('fbf-tweaks') || 'null');
      return { ...TWEAK_DEFAULTS, ...(saved || {}) };
    } catch { return TWEAK_DEFAULTS; }
  });
  const [tweakMode, setTweakMode] = useStA(false);

  const [screen, setScreen] = useStA('listen');
  const [historyOpen, setHistoryOpen] = useStA(false);
  const [listening, setListening] = useStA(false);
  const [transcript, setTranscript] = useStA('');
  const [connStatus, setConnStatus] = useStA('idle'); // idle | connecting | live | resolving | error
  const [errMsg, setErrMsg] = useStA('');
  const [liveSingle, setLiveSingle] = useStA(null);
  const [liveJob, setLiveJob] = useStA(null);
  const [liveCapacity, setLiveCapacity] = useStA(null);
  const [liveVeh, setLiveVeh] = useStA(null);

  // persist tweaks
  useEfA(() => {
    try { localStorage.setItem('fbf-tweaks', JSON.stringify(tweaks)); } catch {}
  }, [tweaks]);

  // Accent
  useEfA(() => {
    const a = ACCENTS[tweaks.accent] || ACCENTS.electric;
    const root = document.documentElement;
    root.style.setProperty('--accent', a.hex);
    root.style.setProperty('--acc-dim', a.dim);
    root.style.setProperty('--acc-glow', a.glow);
  }, [tweaks.accent]);

  // Sync screen tweak to state (for design-tool demo only; does not affect live flow)
  useEfA(() => {
    if (tweaks.screen && tweaks.screen !== screen) setScreen(tweaks.screen);
    // eslint-disable-next-line
  }, [tweaks.screen]);

  // Wire voice events once
  useEfA(() => {
    const V = window.FillVoice;
    if (!V) {
      setErrMsg('Voice module not loaded');
      return;
    }
    V.on('status', (s) => {
      if (s === 'connecting') setConnStatus('connecting');
      else if (s === 'connected') setConnStatus('live');
      else if (s === 'resolving') setConnStatus('resolving');
      else if (s === 'disconnected') {
        setConnStatus('idle');
        setListening(false);
      }
    });
    V.on('transcript', (args) => {
      setTranscript(buildTranscript(args));
    });
    V.on('result', ({ args, response }) => {
      if (!response) return;
      if (response.status === 'ok' && response.kind === 'spec') {
        const veh = responseToVeh(response, args);
        setLiveVeh(veh);
        setLiveCapacity(resultToCapacity(response, args));
        setLiveSingle(null);
        setLiveJob(null);
        setScreen('capacity');
        setTweaks((t) => ({ ...t, screen: 'capacity' }));
      } else if (response.status === 'ok' && response.kind === 'overview') {
        const veh = responseToVeh(response, args);
        setLiveVeh(veh);
        setLiveJob(resultToJob(response, args));
        setLiveSingle(null);
        setLiveCapacity(null);
        setScreen('job');
        setTweaks((t) => ({ ...t, screen: 'job' }));
      } else if (response.status === 'ok' && response.kind === 'miss') {
        setTranscript((response.message || 'No match') + ' — say another vehicle');
      } else if (response.status === 'ok' && response.kind === 'clarify') {
        setTranscript('Clarify: ' + (response.message || 'engine?'));
      } else if (response.status === 'error') {
        setErrMsg(response.message || 'Lookup error');
      }
    });
    V.on('error', (e) => {
      const m = e instanceof Error ? e.message : (e && e.message) || 'Voice error';
      setErrMsg(m);
      setConnStatus('error');
      setListening(false);
    });
  }, []);

  // Tweak mode protocol (design tool hook — left intact)
  useEfA(() => {
    const handler = (ev) => {
      if (ev.data?.type === '__activate_edit_mode') setTweakMode(true);
      if (ev.data?.type === '__deactivate_edit_mode') setTweakMode(false);
    };
    window.addEventListener('message', handler);
    try { window.parent.postMessage({ type: '__edit_mode_available' }, '*'); } catch {}
    return () => window.removeEventListener('message', handler);
  }, []);

  useEfA(() => {
    try {
      window.parent.postMessage({
        type: '__edit_mode_set_keys',
        edits: {
          accent: tweaks.accent,
          density: tweaks.density,
          units: tweaks.units,
          layout: tweaks.layout,
          screen: tweaks.screen
        }
      }, '*');
    } catch {}
  }, [tweaks]);

  const go = (s) => {
    setScreen(s);
    setTweaks((t) => ({ ...t, screen: s }));
  };

  const onToggleMic = useCbA(() => {
    setErrMsg('');
    const V = window.FillVoice;
    if (!V) { setErrMsg('Voice not ready'); return; }
    if (listening) {
      V.stop();
      setListening(false);
      setConnStatus('idle');
    } else {
      setTranscript('');
      setListening(true);
      V.start();
    }
  }, [listening]);

  const handleDemo = (kind) => {
    // Design-mode demo buttons keep working for marketing screenshots.
    if (kind === 'single' && !liveSingle) setLiveSingle(SINGLE_OIL);
    if (kind === 'job' && !liveJob) setLiveJob(JOB_FULL_SERVICE);
    if (kind === 'capacity' && !liveCapacity) setLiveCapacity(CAPACITY_ONLY);
    if (kind === 'single')   go('single');
    if (kind === 'job')      go('job');
    if (kind === 'capacity') go('capacity');
  };

  const capacityData = liveCapacity || CAPACITY_ONLY;
  const jobData = liveJob || JOB_FULL_SERVICE;
  const singleData = liveSingle || SINGLE_OIL;
  const vehData = liveVeh || DEMO_VEHICLE;

  return (
    <div style={{
      minHeight:'100dvh', background:'var(--black)',
      display:'flex', justifyContent:'center', alignItems:'stretch'
    }}>
      <div style={{
        width:'100%', maxWidth:480,
        height:'100dvh', position:'relative', overflow:'hidden',
        background:'var(--bg)',
        backgroundImage:
          'linear-gradient(rgba(0,229,255,0.018) 1px, transparent 1px),' +
          'linear-gradient(90deg, rgba(0,229,255,0.018) 1px, transparent 1px)',
        backgroundSize:'32px 32px'
      }}>
        <TopBar
          wake={listening || connStatus === 'live'}
          onHistory={() => setHistoryOpen(true)}
          onHome={() => go('listen')}
        />

        {screen === 'listen' && (
          <ListenScreen
            state={{ listening, transcript: errMsg ? ('⚠ ' + errMsg) : transcript }}
            onDemo={handleDemo}
            onToggle={onToggleMic}
            connStatus={connStatus === 'live' ? 'live' : connStatus === 'idle' ? 'warming' : connStatus}
          />
        )}

        {screen === 'single' && (
          <SingleFluidScreen
            data={singleData}
            veh={vehData}
            onBack={() => go('listen')}
            onWrong={() => go('safety')}
            density={tweaks.density}
            units={tweaks.units}
          />
        )}

        {screen === 'job' && (
          <JobTableScreen
            data={jobData}
            veh={vehData}
            onBack={() => go('listen')}
            onItemTap={() => {}}
            units={tweaks.units}
            layout={tweaks.layout}
          />
        )}

        {screen === 'capacity' && (
          <CapacityScreen
            data={capacityData}
            veh={vehData}
            onBack={() => go('listen')}
            units={tweaks.units}
            density={tweaks.density}
          />
        )}

        {screen === 'safety' && (
          <SafetyWall data={SAFETY_DOT} onAck={() => go('single')} />
        )}

        <HistoryDrawer open={historyOpen} onClose={() => setHistoryOpen(false)} onPick={(kind) => { setHistoryOpen(false); go(kind); }} />
      </div>

      <TweaksPanel tweaks={tweaks} setTweaks={setTweaks} visible={tweakMode} />
    </div>
  );
}

function HistoryDrawer({ open, onClose, onPick }) {
  return (
    <>
      <div style={{
        position:'absolute', inset:0, background:'rgba(0,0,0,0.76)',
        zIndex:80, opacity: open ? 1 : 0,
        pointerEvents: open ? 'all' : 'none',
        transition:'opacity 0.22s'
      }} onClick={onClose} />
      <div style={{
        position:'absolute', bottom:0, left:0, right:0,
        background:'var(--panel)', borderTop:'3px solid var(--accent)',
        zIndex:90,
        transform: open ? 'translateY(0)' : 'translateY(100%)',
        transition:'transform 0.28s cubic-bezier(0.32,0.72,0,1)',
        maxHeight:'76dvh',
        display:'flex', flexDirection:'column'
      }}>
        <div style={{width:40, height:4, background:'var(--border-h)', borderRadius:2, margin:'11px auto 0', flexShrink:0}} />
        <div style={{display:'flex', justifyContent:'space-between', alignItems:'center', padding:'10px 16px 9px', borderBottom:'2px solid var(--border)', flexShrink:0}}>
          <div style={{fontFamily:"'DM Mono',monospace", fontSize:8, letterSpacing:'0.22em', textTransform:'uppercase', color:'var(--muted)'}}>
            Recent fluids — tap to re-open
          </div>
          <button onClick={onClose} style={{
            background:'none', border:'2px solid var(--border-h)', color:'var(--mid)',
            fontFamily:"'DM Mono',monospace", fontSize:8,
            letterSpacing:'0.14em', textTransform:'uppercase',
            cursor:'pointer', padding:'5px 12px'
          }}>CLOSE</button>
        </div>
        <div style={{overflowY:'auto', flex:1, WebkitOverflowScrolling:'touch'}}>
          {HISTORY.map((h, i) => (
            <div key={i} onClick={() => onPick(i === 0 ? 'single' : 'capacity')} style={{
              display:'flex', justifyContent:'space-between', alignItems:'center',
              padding:'13px 16px', borderBottom:'1px solid var(--border)', cursor:'pointer'
            }}>
              <div style={{display:'flex', flexDirection:'column', gap:3}}>
                <div style={{fontFamily:"'DM Mono',monospace", fontSize:8, color:'var(--muted)', letterSpacing:'0.14em', textTransform:'uppercase'}}>
                  {h.veh} · {h.when}
                </div>
                <div style={{fontFamily:"'Barlow Condensed',sans-serif", fontWeight:700, fontSize:17, color:'var(--text-d)', textTransform:'uppercase', letterSpacing:'0.04em'}}>
                  {h.q}
                </div>
              </div>
              <div style={{textAlign:'right'}}>
                <div style={{fontFamily:"'Barlow Condensed',sans-serif", fontWeight:900, fontSize:36, color:'var(--accent)', lineHeight:1, opacity:0.55}}>
                  {h.val}
                </div>
                <div style={{fontFamily:"'DM Mono',monospace", fontSize:8, color:'var(--dim)', letterSpacing:'0.1em'}}>
                  {h.unit}
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
