// Logo, Mascot, Easter Eggs, Plumber's Brain AI teaser
const { useState: useStateF, useEffect: useEffectF, useRef: useRefF } = React;

// ============== LOGO (SVG, redrawn from brand mark) ==============
function CBLogo({ size = 44, light = true }) {
  const ink = light ? '#0e1a2b' : '#fff';
  return (
    <svg width={size} height={size} viewBox="0 0 64 64" fill="none" aria-label="Clog Busterz" style={{display:'block'}}>
      {/* Toilet base */}
      <rect x="8" y="38" width="22" height="14" rx="2" stroke={ink} strokeWidth="3" fill="none"/>
      <rect x="6" y="50" width="26" height="4" rx="1" fill={ink}/>
      <rect x="10" y="22" width="6" height="18" rx="1" stroke={ink} strokeWidth="3" fill="none"/>
      {/* Plunger */}
      <line x1="22" y1="6" x2="22" y2="30" stroke={ink} strokeWidth="3" strokeLinecap="round"/>
      <ellipse cx="22" cy="33" rx="11" ry="6" stroke={ink} strokeWidth="3" fill="none"/>
      <ellipse cx="22" cy="32" rx="11" ry="3" fill={ink}/>
      {/* Spark */}
      <circle cx="50" cy="14" r="2" fill={ink}/>
      <circle cx="56" cy="22" r="1.5" fill={ink}/>
      <circle cx="48" cy="24" r="1" fill={ink}/>
    </svg>
  );
}
window.CBLogo = CBLogo;

// ============== MASCOT — Pipe Pete ==============
// A friendly little pipe-wrench character that follows scroll & reacts to clicks
const PETE_SCHEMES = [
  { id: 'electric', name: 'ELECTRIC', face: '#00e0ff', hat: '#ff2d6f', glow: '#00e0ff', bubble: '#00e0ff', stroke: '#0e1a2b', text: '#0e1a2b' },
  { id: 'lime', name: 'TOXIC LIME', face: '#caff00', hat: '#ff2d6f', glow: '#caff00', bubble: '#caff00', stroke: '#0e1a2b', text: '#0e1a2b' },
  { id: 'magenta', name: 'HOT MAGENTA', face: '#ff2d6f', hat: '#00e0ff', glow: '#ff2d6f', bubble: '#ff2d6f', stroke: '#0e1a2b', text: '#fff' },
  { id: 'sunset', name: 'SUNSET', face: '#ff8a3d', hat: '#5b2dff', glow: '#ff8a3d', bubble: '#ff8a3d', stroke: '#0e1a2b', text: '#0e1a2b' },
];

const PETE_FACTS = [
  { text: "A plumbing trap is built to hold a liquid seal that blocks sewer gas while still letting wastewater flow.", source: "KY State Plumbing Code - 815 KAR 20:010" },
  { text: "A trap primer exists for rarely used drains because trap water can evaporate over time.", source: "KY State Plumbing Code - 815 KAR 20:010" },
  { text: "Kentucky's plumbing code requires a water heater to stay accessible for inspection, repair, and replacement.", source: "KY State Plumbing Code - 815 KAR 20:055" },
  { text: "Kentucky code says water-heater temperature and pressure relief valves must follow the manufacturer's requirements.", source: "KY State Plumbing Code - 815 KAR 20:055" },
  { text: "A new or replacement water heater installation requires a Kentucky plumbing permit.", source: "KY State Plumbing Code - 815 KAR 20:050" },
  { text: "Cleaning out a waste or sewer pipe is listed separately from work that requires a Kentucky plumbing permit.", source: "KY State Plumbing Code - 815 KAR 20:050" },
  { text: "Rheem water-heater manuals warn not to plug the relief valve outlet.", source: "Rheem residential water-heater manuals" },
  { text: "Bradford White manuals warn not to thread, plug, or cap the T&P relief discharge line.", source: "Bradford White installation manuals" },
  { text: "Navien recommends annual tankless maintenance because scale can interfere with water-heater parts.", source: "Navien maintenance guidance" },
  { text: "Rinnai tells owners to keep tankless manuals for future reference and have regular maintenance performed.", source: "Rinnai tankless installation and operation manuals" },
  { text: "Kentucky code defines a vent system as piping that protects trap seals from siphonage and back pressure.", source: "KY State Plumbing Code - 815 KAR 20:010" },
  { text: "Kentucky code lists PVC Schedule 40 and 80 as accepted DWV materials when produced and labeled to the required ASTM specs.", source: "KY State Plumbing Code - 815 KAR 20:090" },
];

const PB_APPROVED_SOURCES = [
  {
    id: 'ky-water-heater',
    label: 'KY State Plumbing Code - 815 KAR 20:055',
    url: 'https://apps.legislature.ky.gov/law/kar/titles/815/020/055/',
    tags: ['water heater', 'hot water', 'heater', 't&p', 'relief valve', 'temperature', 'pressure', 'accessible', 'access'],
    guidance: 'A water heater must be properly connected to the hot and cold water supply and accessible for inspection, repair, and replacement. Temperature and pressure relief valves must be installed in accordance with manufacturer requirements.',
  },
  {
    id: 'ky-permits',
    label: 'KY State Plumbing Code - 815 KAR 20:050',
    url: 'https://apps.legislature.ky.gov/law/kar/titles/815/020/050/',
    tags: ['permit', 'inspection', 'replace', 'replacement', 'install', 'installation', 'water heater', 'sewer', 'water service', 'backflow', 'homeowner permit'],
    guidance: 'Kentucky requires a plumbing permit for new plumbing installations, moving or relocating fixture/soil/waste openings, new or replacement house sewers, new or replacement water service, adding a backflow prevention device, and new or replacement water heaters. Cleaning out waste or sewer pipes is listed as work that does not require a permit.',
  },
  {
    id: 'ky-traps',
    label: 'KY State Plumbing Code - 815 KAR 20:010',
    url: 'https://apps.legislature.ky.gov/law/kar/titles/815/020/010/',
    tags: ['trap', 'p trap', 'p-trap', 'sewer gas', 'sewer smell', 'dry drain', 'floor drain', 'vent', 'trap primer', 'smell'],
    guidance: 'Kentucky code defines a trap as a fitting or device that provides a liquid seal to prevent sewer gases from escaping while allowing sewage or wastewater to flow. It also defines trap primers as devices or piping that maintain a water seal where infrequent use could let the trap seal evaporate.',
  },
  {
    id: 'ky-dwv',
    label: 'KY State Plumbing Code - 815 KAR 20:090',
    url: 'https://apps.legislature.ky.gov/law/kar/titles/815/020/090/',
    tags: ['drain', 'waste', 'vent', 'dwv', 'pvc', 'abs', 'cast iron', 'pipe material', 'basement floor drain', 'backwater', 'backflow'],
    guidance: 'Kentucky code sets the accepted methods and materials for soil, waste, vent systems, traps, and clean-outs. It lists accepted DWV materials and requires basement floor drains to be properly trapped, vented, readily accessible for cleaning, and sized for the intended use.',
  },
  {
    id: 'rheem-relief',
    label: 'Rheem water-heater manufacturer manuals',
    url: 'https://www.rheem.com/support/',
    tags: ['rheem', 'water heater', 'relief valve', 't&p', 'tp valve', 'pressure relief', 'thermal expansion', 'dripping relief'],
    guidance: 'Rheem water-heater manuals warn not to plug the relief valve outlet. If a temperature and pressure relief valve discharges periodically, the manual points to possible thermal expansion in a closed water system and says to contact the water supplier or plumbing contractor.',
  },
  {
    id: 'bradford-white-relief',
    label: 'Bradford White installation manuals',
    url: 'https://www.bradfordwhite.com/professionals/technical-support/manuals/',
    tags: ['bradford white', 'water heater', 'relief valve', 't&p', 'tp valve', 'discharge line', 'pressure relief'],
    guidance: 'Bradford White manuals require a properly sized temperature and pressure relief valve and warn that the discharge line must not be threaded, plugged, or capped. They also warn not to place a valve between the relief valve and the tank.',
  },
  {
    id: 'rinnai-gas-service',
    label: 'Rinnai tankless manufacturer manuals',
    url: 'https://www.rinnai.us/residential/product-registration-and-support/product-support',
    tags: ['rinnai', 'tankless', 'gas', 'gas smell', 'combustion', 'venting', 'service', 'qualified professional'],
    guidance: 'Rinnai tankless manuals warn that if gas is smelled, people should not try to light appliances, touch electrical switches, or use a phone in the building. They state installation and service must be performed by a trained and qualified professional, service agency, or gas supplier.',
  },
  {
    id: 'rinnai-maintenance',
    label: 'Rinnai tankless maintenance guidance',
    url: 'https://www.rinnai.us/residential/flushing-my-rinnai-tankless-water-heater',
    tags: ['rinnai', 'tankless', 'flush', 'descale', 'scale', 'maintenance', 'filter'],
    guidance: 'Rinnai maintenance guidance includes powering off the unit, shutting off gas or the electrical breaker as applicable, and closing service valves before flushing. Rinnai manuals also call for periodic air-filter inspection and cleaning.',
  },
  {
    id: 'navien-maintenance',
    label: 'Navien tankless maintenance guidance',
    url: 'https://www.navieninc.com/blog/notice/tankless-water-heater-maintenance',
    tags: ['navien', 'tankless', 'descale', 'scale', 'maintenance', 'annual', 'hard water', 'heat exchanger'],
    guidance: 'Navien recommends annual tankless maintenance. Navien says annual maintenance removes mineral deposits, also called scale, that can interfere with the heat exchanger and other parts, and notes that a certified technician helps protect the warranty.',
  },
];

const PB_EMERGENCY_RE = /\b(gas smell|smell gas|sewage inside|sewer backup|raw sewage|flood|flooding|standing water|soaked drywall|ceiling leak|electrical|sparking|shock)\b/i;
const PB_ESCALATE_TEXT = "I do not have a manufacturer recommendation or Kentucky State Plumbing Code source loaded for that exact question, so I would rather send it to a real Clog Busterz plumber than guess.";
// The Sheetz "ask" brain — grounded in CB's REAL pricebook, so it can give honest "starting at" pricing
// and learns as the pricebook grows. The website Brain calls this for service/price questions.
const PB_SHEETZ_ASK = 'https://tech.sheetzz.com/api/ask';
const PB_SCAN_PLATE = 'https://tech.sheetzz.com/api/scan-plate';
const PB_FLOOD_LEAD = 'https://tech.sheetzz.com/api/flood-lead';
const PB_BOOK = 'https://tech.sheetzz.com/api/book';
// 🥊 Second Opinion — a customer snaps/uploads a competitor's quote (or the leak / equipment plate) and
// the SAME engine Plunger Pete uses in Messenger reads it and gives an honest verdict. Public + hardened.
const PB_SECOND_OPINION = 'https://tech.sheetzz.com/api/second-opinion';
// Water-heater guided flow trigger: a water-heater question with a service/price/leak angle.
const PB_WH_RE = /\b(water ?heater|hot water heater|tankless)\b/i;
const PB_WH_INTENT_RE = /\b(leak|leaking|replace|replacement|install|new|old|cost|how much|price|quote|estimate|broken|not working|no hot water|dripping)\b/i;
// Buying / problem intent — when present, route to the Sheetz brain + push to book (don't dead-end).
const PB_SERVICE_RE = /\b(how much|how many|cost|costs|price|pricing|quote|estimate|ballpark|install|installation|replace|replacement|book|booking|appointment|schedule|come out|send someone|same day|repair|fix|fixing|unclog|clog|clogged|backed up|leak|leaking|broken|not working|no hot water)\b/i;

function normalizeBrainText(text) {
  return String(text || '').toLowerCase().replace(/[^a-z0-9&+\s-]/g, ' ');
}

function findApprovedBrainSources(question) {
  const q = normalizeBrainText(question);
  return PB_APPROVED_SOURCES
    .map(source => {
      const score = source.tags.reduce((sum, tag) => sum + (q.includes(tag) ? 1 : 0), 0);
      return { source, score };
    })
    .filter(item => item.score > 0)
    .sort((a, b) => b.score - a.score)
    .slice(0, 3)
    .map(item => item.source);
}

function buildLocalBrainAnswer(question, sources) {
  if (PB_EMERGENCY_RE.test(question)) {
    const gas = /\b(gas|propane|lp)\b/i.test(question);
    const electrical = !gas && /\b(electrical|sparking|spark|shock|electrocut)\b/i.test(question);
    const water = !gas && !electrical && /\b(flood|flooding|standing water|water everywhere|soaked|ceiling leak|burst|overflow)\b/i.test(question);
    const sewage = !gas && !electrical && !water && /\b(sewage|sewer|raw sewage)\b/i.test(question);
    const text = gas
      ? "🚨 A gas smell is an emergency. First, get everyone out of the building — and don't flip light switches, unplug anything, or use a phone inside. We recommend calling 911 or the fire department, plus your gas company's emergency line, from a safe spot outside. We can still get a plumber out to you — book below and your visit will be flagged as an emergency so dispatch jumps on it. (I won't troubleshoot a gas leak in chat.)"
      : electrical
      ? "🚨 Anything sparking, shocking, or live electricity near water is a real emergency — stay clear of it and call 911 or your power company. Once it's safe we'll handle the plumbing side. Book below and it'll be flagged as an emergency so dispatch jumps on it."
      : water
      ? "🚨 Your safety first: don't walk or stand in standing water if it's anywhere near outlets, appliances, or your electrical panel — water and electricity together are a serious shock risk. If the water is near anything electrical, stay out of that area and call 911. If you can safely reach your main water shutoff from a dry spot, shutting it off helps stop the flow. We can get a crew out fast — book below and it'll be flagged as an emergency. (I won't troubleshoot flooding or electrical in chat.)"
      : sewage
      ? "Sewage on the floor is a health hazard, though it's usually not a 911 situation. Keep kids and pets away, try not to touch it, and don't run water or flush on that line until we get there. We'll get a crew out fast — book below and it'll be flagged as an emergency so we prioritize it."
      : "That can be urgent. Book below (it'll be flagged as an emergency) or call us right now at 859-408-3382 and we'll get someone moving.";
    return {
      text,
      escalate: question,
      sources: sources.length ? sources : [PB_APPROVED_SOURCES.find(s => s.id === 'rinnai-gas-service')].filter(Boolean),
    };
  }
  if (!sources.length) return { text: PB_ESCALATE_TEXT, escalate: question, sources: [] };
  const labels = sources.map(s => s.label).join('; ');
  const guidance = sources.map(s => s.guidance).join(' ');
  return {
    text: `Based only on loaded manufacturer/code sources: ${guidance}\n\nSource(s): ${labels}\n\nFor installs, replacements, gas work, sewage, flooding, or anything model-specific, use a licensed plumber so the work follows the exact manual and Kentucky code.`,
    escalate: null,
    sources,
  };
}

// Floating "Plumbing Fact" card — replaces the old neon Pipe Pete mascot. Surfaces the same real,
// cited KY-code + manufacturer facts (PETE_FACTS) in a clean, on-brand way. Appears once past the hero.
function PipePete() {
  const [shown, setShown] = useStateF(false);
  const [dismissed, setDismissed] = useStateF(false);
  const [idx, setIdx] = useStateF(() => Math.floor(Math.random() * PETE_FACTS.length));

  useEffectF(() => {
    const onScroll = () => {
      const hero = document.querySelector('.hero');
      const heroBottom = hero ? hero.getBoundingClientRect().bottom : window.innerHeight;
      setShown(!!hero && heroBottom < 140);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  if (dismissed || !shown) return null;
  const fact = PETE_FACTS[idx % PETE_FACTS.length];
  // Advance to a DIFFERENT random fact.
  const nextFact = () => setIdx((i) => (i + 1 + Math.floor(Math.random() * (PETE_FACTS.length - 1))) % PETE_FACTS.length);

  return (
    <div className="cbfact-wrap" role="note" aria-label="Plumbing fact">
      <div className="cbfact-card">
        <div className="cbfact-head">
          <span className="cbfact-badge">💧 PLUMBING FACT</span>
          <button className="cbfact-x" onClick={() => setDismissed(true)} aria-label="Dismiss plumbing fact">×</button>
        </div>
        <p className="cbfact-body">{fact.text}</p>
        <div className="cbfact-foot">
          <span className="cbfact-src">{fact.source}</span>
          <button className="cbfact-next" onClick={nextFact}>Next fact →</button>
        </div>
      </div>
    </div>
  );
}
window.PipePete = PipePete;

// ============== KONAMI / "PLUNGER" easter egg ==============
function PlungerRain() {
  const [active, setActive] = useStateF(false);

  useEffectF(() => {
    let buf = '';
    const trigger = 'plunger';
    const onKey = (e) => {
      if (!/^[a-z]$/i.test(e.key)) return;
      buf = (buf + e.key.toLowerCase()).slice(-trigger.length);
      if (buf === trigger) {
        setActive(true);
        setTimeout(() => setActive(false), 6000);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  if (!active) return null;
  const drops = Array.from({length: 28}).map((_, i) => ({
    left: Math.random()*100,
    delay: Math.random()*2,
    dur: 2 + Math.random()*2,
    rot: Math.random()*720 - 360,
    size: 28 + Math.random()*32,
    key: i,
  }));
  return (
    <div className="plunger-rain" aria-hidden="true">
      {drops.map(d => (
        <div key={d.key} className="plunger-drop" style={{
          left: d.left + '%',
          animationDelay: d.delay + 's',
          animationDuration: d.dur + 's',
          fontSize: d.size + 'px',
          transform: `rotate(${d.rot}deg)`,
        }}>🪠</div>
      ))}
      <div className="plunger-banner">YOU FOUND THE SECRET PLUNGER. $10 OFF — CODE: <strong>PLUNGER10</strong></div>
    </div>
  );
}
window.PlungerRain = PlungerRain;

// ============== PLUMBER'S BRAIN AI — teaser + chat ==============
// Small inline phone capture used inside the Brain's FloodBusterz handoff step.
function PBPhoneInput({ onSubmit }) {
  const [v, setV] = useStateF('');
  const ok = v.replace(/\D/g, '').length >= 10;
  return (
    <div className="pb-chat-input-row" style={{ marginTop: 8 }}>
      <input className="pb-chat-input" placeholder="Your phone number" value={v} inputMode="tel"
        onChange={e => setV(e.target.value)} onKeyDown={e => e.key === 'Enter' && ok && onSubmit(v)} />
      <button className="pb-chat-send" disabled={!ok} onClick={() => ok && onSubmit(v)}>SEND →</button>
    </div>
  );
}

// Downscale a phone photo to a reasonable JPEG so it fits under the API body limit and emails quickly.
function resizeImage(file, maxDim = 1280, quality = 0.7) {
  return new Promise((resolve) => {
    try {
      const img = new Image();
      const url = URL.createObjectURL(file);
      img.onload = () => {
        let w = img.width, h = img.height;
        if (w >= h && w > maxDim) { h = Math.round(h * maxDim / w); w = maxDim; }
        else if (h > w && h > maxDim) { w = Math.round(w * maxDim / h); h = maxDim; }
        const c = document.createElement('canvas');
        c.width = w; c.height = h;
        c.getContext('2d').drawImage(img, 0, 0, w, h);
        URL.revokeObjectURL(url);
        resolve(c.toDataURL('image/jpeg', quality));
      };
      img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };
      img.src = url;
    } catch (e) { resolve(null); }
  });
}

// FloodBusterz handoff form: phone + up to 4 damage photos that get emailed to the FloodBusterz salesperson.
function PBFloodForm({ onSubmit }) {
  const [phone, setPhone] = useStateF('');
  const [photos, setPhotos] = useStateF([]);
  const [working, setWorking] = useStateF(false);
  const ok = phone.replace(/\D/g, '').length >= 10;
  const addPhotos = async (files) => {
    setWorking(true);
    const picked = Array.from(files).slice(0, 4 - photos.length);
    const out = [];
    for (const f of picked) { const d = await resizeImage(f, 1280, 0.7); if (d) out.push(d); }
    setPhotos((p) => [...p, ...out].slice(0, 4));
    setWorking(false);
  };
  return (
    <div style={{ marginTop: 8 }}>
      <div className="pb-chat-input-row">
        <input className="pb-chat-input" placeholder="Your phone number" value={phone} inputMode="tel" onChange={(e) => setPhone(e.target.value)} />
      </div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 8, flexWrap: 'wrap' }}>
        <label className="pb-quick" style={{ cursor: 'pointer' }}>
          📷 Add photos{photos.length ? ` (${photos.length})` : ''}
          <input type="file" accept="image/*" capture="environment" multiple style={{ display: 'none' }} onChange={(e) => { if (e.target.files && e.target.files.length) addPhotos(e.target.files); }} />
        </label>
        <button className="pb-chat-send" disabled={!ok || working} onClick={() => ok && !working && onSubmit({ phone, photos })}>{working ? '…' : 'SEND →'}</button>
      </div>
      {photos.length > 0 && <div style={{ fontSize: 11, color: '#7fae9a', marginTop: 4 }}>{photos.length} photo{photos.length > 1 ? 's' : ''} attached — these go to FloodBusterz (up to 4)</div>}
    </div>
  );
}

// Generic inline text capture for the in-chat booking collector (name / phone / address).
function PBTextInput({ placeholder, kind, cta, onSubmit }) {
  const [v, setV] = useStateF('');
  const ok = kind === 'phone' ? v.replace(/\D/g, '').length >= 10 : v.trim().length >= 2;
  return (
    <div className="pb-chat-input-row" style={{ marginTop: 8 }}>
      <input className="pb-chat-input" placeholder={placeholder} value={v} inputMode={kind === 'phone' ? 'tel' : 'text'}
        onChange={e => setV(e.target.value)} onKeyDown={e => e.key === 'Enter' && ok && onSubmit(v.trim())} />
      <button className="pb-chat-send" disabled={!ok} onClick={() => ok && onSubmit(v.trim())}>{cta || 'NEXT →'}</button>
    </div>
  );
}

function PlumberBrain() {
  const [open, setOpen] = useStateF(false);
  const [input, setInput] = useStateF('');
  const [busy, setBusy] = useStateF(false);
  const [flow, setFlow] = useStateF({});
  const [booking, setBooking] = useStateF(null); // in-chat booking collector context
  const [fabShown, setFabShown] = useStateF(false);
  const [msgs, setMsgs] = useStateF([
    { role: 'pb', text: "Hey — I'm Plumber's Brain. Ask me anything: code and permit questions come straight from Kentucky code + manufacturer specs, and for repairs or replacements I'll give you honest “starting at” pricing and get you on the schedule. Anything I'm not sure on, a real Clog Busterz plumber takes over." }
  ]);
  const scrollRef = useRefF(null);

  useEffectF(() => {
    const onScroll = () => {
      const hero = document.querySelector('.hero');
      const heroBottom = hero ? hero.getBoundingClientRect().bottom : window.innerHeight;
      setFabShown(!!hero && heroBottom < 140);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    // Let anything on the page open the Brain chat (e.g. the mobile rail's Message button).
    const onOpen = () => setOpen(true);
    window.addEventListener('cb-open-brain', onOpen);
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('cb-open-brain', onOpen); };
  }, []);

  useEffectF(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [msgs, busy]);

  const pushPB = (msg) => setMsgs(m => [...m, { role: 'pb', ...msg }]);

  // ── In-chat booking: collect name → phone → address → confirm → create the job (no leaving the Brain) ──
  const startInChatBooking = (question, service, emergency) => {
    setBooking({ service: service || 'Service request', q: question || '', emergency: !!emergency });
    pushPB({ text: emergency ? "Let's get you on the schedule right away — I'll flag this as an emergency so dispatch jumps on it. First, what's your name?" : "Let's get you on the schedule — I'll grab a few quick details. First, what's your name?", input: 'book-name' });
  };
  const bookName = (v) => { setBooking(b => ({ ...(b || {}), name: v })); pushPB({ text: `Thanks, ${v.split(' ')[0]}! What's the best phone number to reach you?`, input: 'book-phone' }); };
  const bookPhone = (v) => { setBooking(b => ({ ...(b || {}), phone: v })); pushPB({ text: "Got it. And the service address? (street + city)", input: 'book-address' }); };
  const bookAddress = (v) => {
    const b = { ...(booking || {}), address: v };
    setBooking(b);
    pushPB({
      text: `Perfect — here's your ticket:\n• ${b.name || ''}\n• ${b.phone || ''}\n• ${v}\n• ${b.service}\n\nReady to send it to our dispatch team? They'll text you to lock in a time.`,
      options: [{ label: '✅ Yes — book it', action: 'book:confirm' }, { label: 'Not yet', action: 'book:cancel' }],
    });
  };
  const confirmBooking = async () => {
    setBusy(true);
    const b = booking || {};
    try {
      const r = await fetch(PB_BOOK, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: b.name, phone: b.phone, address: b.address, service: b.service,
          emergency: !!b.emergency,
          urgency: b.emergency ? 'emergency' : '',
          notes: (b.emergency ? '🚨 EMERGENCY · ' : '') + "Booked in-chat via Plumber's Brain." + (b.q ? ` Customer asked: ${b.q}` : ''),
          ref: (window.CB_DISPATCH && window.CB_DISPATCH.refCode) ? window.CB_DISPATCH.refCode() : '',
        }),
      });
      const j = await r.json();
      pushPB({ text: (j && j.message) || "✓ Request received! Our office will text you shortly to confirm a time.", booked: true });
    } catch (_) {
      pushPB({ text: "Hmm — I couldn't reach dispatch just now. Please call us at 859-408-3382 and we'll get you set up right away.", cta: 'urgent' });
    }
    setBooking(null);
    setBusy(false);
  };

  // ── Guided water-heater flow: fuel → data plate → estimate → FloodBusterz cross-sell → lead ──
  const startWaterHeaterFlow = (q) => {
    setFlow({ origQ: q });
    pushPB({
      text: "Sounds like a water heater — let's get you a real number. First: is it gas or electric? (Gas has a flame and a vent pipe up top; electric just has a power cable.)",
      options: [
        { label: '🔥 Gas', action: 'wh-fuel:gas' },
        { label: '⚡ Electric', action: 'wh-fuel:electric' },
        { label: 'Not sure', action: 'wh-fuel:unsure' },
      ],
    });
    setBusy(false);
  };

  const whEstimate = async (f) => {
    setBusy(true);
    const fuelWord = f.fuel === 'gas' ? 'gas' : f.fuel === 'electric' ? 'electric' : '';
    const age = f.plate && f.plate.ageYears;
    const unitBits = [f.plate && f.plate.brand, f.plate && f.plate.capacityGallons ? f.plate.capacityGallons + '-gallon' : '', fuelWord].filter(Boolean).join(' ');
    const unitLabel = ((unitBits || (fuelWord ? fuelWord + ' water heater' : 'water heater'))) + (age ? ` ~${age}yr` : '') + (/leak/i.test(f.origQ || '') ? ' (leaking)' : '');
    const ageBit = age ? ` that's about ${age} years old` : '';
    const question = `Roughly what does it cost to replace a leaking ${unitBits || fuelWord} water heater${ageBit}? Give a friendly starting-at range${age && age >= 10 ? ', gently note a unit that age is usually worth replacing rather than repairing' : ''}, and remind them the exact price comes after we see it.`;
    let answer = '';
    try {
      const r = await fetch(PB_SHEETZ_ASK, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question }) });
      const j = await r.json();
      if (j && j.ok && j.answer) answer = j.answer;
    } catch (_) {}
    if (!answer) answer = "Water heater replacement depends on the unit and the install — best to have us take a quick look. Book a visit or call and we'll give you an exact number.";
    setFlow(prev => ({ ...prev, unitLabel }));
    pushPB({ text: answer, cta: 'book', service: 'Water Heater Install', q: f.origQ });
    pushPB({
      text: "One more thing — since it's leaking, is there water on the floor, wet baseboards, or a damp smell? Our sister company FloodBusterz can dry it out before it warps your floors or grows mold. Want them to reach out?",
      options: [{ label: 'Yes — have FloodBusterz reach out', action: 'wh-flood:yes' }, { label: 'No, just the water heater', action: 'wh-flood:no' }],
    });
    setBusy(false);
  };

  const submitPlate = async (dataUrl) => {
    if (busy) return;
    setBusy(true);
    setMsgs(m => [...m, { role: 'me', text: '📷 (data plate photo)' }]);
    let plate = null, summary = '';
    try {
      const r = await fetch(PB_SCAN_PLATE, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ photo: dataUrl }) });
      const j = await r.json();
      if (j && j.ok) { plate = j.plate; summary = j.summary || ''; }
    } catch (_) {}
    const nf = { ...flow, plate };
    setFlow(nf);
    pushPB({ text: plate && summary ? `Nice — that's a ${summary}. Let me get you a number…` : "Couldn't quite read that plate — no worries, we'll confirm the exact unit on site. Here's a ballpark…" });
    await whEstimate(nf);
  };

  const submitFloodLead = async ({ phone, photos }) => {
    if (busy) return;
    setBusy(true);
    const n = (photos || []).length;
    setMsgs(m => [...m, { role: 'me', text: phone + (n ? ` · ${n} photo${n > 1 ? 's' : ''}` : '') }]);
    try {
      const r = await fetch(PB_FLOOD_LEAD, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone, photos: photos || [], notes: flow.origQ || '', unit: flow.unitLabel || '' }) });
      const j = await r.json();
      pushPB({ text: (j && j.message) || "Done — FloodBusterz will reach out to scope the dry-out. Want to also get the water heater on the schedule?", cta: 'book', service: 'Water Heater Install', q: flow.origQ });
    } catch (_) {
      pushPB({ text: "Got it — FloodBusterz will get your number. Want to book the water heater fix too?", cta: 'book', service: 'Water Heater Install', q: flow.origQ });
    }
    setBusy(false);
  };

  // Central handler for the guided-flow option buttons.
  const handleOption = async (action, label) => {
    if (busy) return;
    setMsgs(m => [...m, { role: 'me', text: label }]);
    const [key, val] = String(action).split(':');
    if (key === 'wh-fuel') {
      const nf = { ...flow, fuel: val };
      setFlow(nf);
      pushPB({
        text: "Got it. If you can, snap a quick photo of the silver data plate on the unit — it lets me nail the size and give you a sharper number. Or just skip and we'll confirm on site.",
        input: 'photo',
        options: [{ label: 'Skip the photo', action: 'wh-plate:skip' }],
      });
      return;
    }
    if (key === 'book') {
      if (val === 'cancel') { setBooking(null); pushPB({ text: "No problem — I'm here whenever you're ready. Anything else I can help with?" }); return; }
      if (val === 'confirm') { await confirmBooking(); return; }
    }
    if (key === 'wh-plate' && val === 'skip') { await whEstimate(flow); return; }
    if (key === 'wh-flood') {
      if (val === 'yes') pushPB({ text: "Smart move — standing water warps floors and grows mold fast. Drop your number, and snap a few photos of the water/damage if you can — they go straight to the FloodBusterz crew so they come prepared. We never share your info outside Clog Busterz.", input: 'flood-form' });
      else pushPB({ text: "No problem. Want to get the water heater on the schedule?", cta: 'book', service: 'Water Heater Install', q: flow.origQ });
      return;
    }
  };

  const send = async (forced) => {
    const q = (typeof forced === 'string' ? forced : input).trim();
    if (!q || busy) return;
    setMsgs(m => [...m, { role: 'me', text: q }]);
    setInput('');
    setBusy(true);

    // 1) Emergency → safety first, then Call/Book. Gas + live electrical get the 911 recommendation;
    //    water/sewage/other stay "urgent" (still bookable, flagged emergency — no alarmist 911).
    if (PB_EMERGENCY_RE.test(q)) {
      const danger911 = /\b(gas|propane|lp|electrical|sparking|spark|shock|electrocut)\b/i.test(q);
      const a = buildLocalBrainAnswer(q, findApprovedBrainSources(q));
      setMsgs(m => [...m, { role: 'pb', text: a.text, sources: a.sources, cta: danger911 ? 'gas' : 'urgent', q }]);
      setBusy(false); return;
    }

    // 1.5) Water-heater + service/price/leak intent → start the guided flow (fuel → plate → estimate → FloodBusterz).
    if (PB_WH_RE.test(q) && PB_WH_INTENT_RE.test(q)) {
      startWaterHeaterFlow(q);
      return;
    }

    // 2) Code / manufacturer question we have a loaded source for → cite it (keeps "source-only" trust),
    //    unless it's really a price/booking ask.
    const approvedSources = findApprovedBrainSources(q);
    const buyingIntent = PB_SERVICE_RE.test(q);
    if (approvedSources.length && !buyingIntent) {
      const a = buildLocalBrainAnswer(q, approvedSources);
      setMsgs(m => [...m, { role: 'pb', text: a.text, sources: a.sources, cta: 'soft', q }]);
      setBusy(false); return;
    }

    // 3) Service / price / "how much" / anything else → ask the Sheetz brain (grounded in our real pricebook).
    try {
      const r = await fetch(PB_SHEETZ_ASK, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question: q }) });
      const j = await r.json();
      if (j && j.ok && j.answer) {
        setMsgs(m => [...m, { role: 'pb', text: j.answer, cta: 'book', q }]);
        setBusy(false); return;
      }
    } catch (_) {}

    // 4) Sheetz unavailable → cite a local source if we have one, else hand to a real plumber (don't guess).
    if (approvedSources.length) {
      const a = buildLocalBrainAnswer(q, approvedSources);
      setMsgs(m => [...m, { role: 'pb', text: a.text, sources: a.sources, cta: 'soft', q }]);
    } else {
      setMsgs(m => [...m, { role: 'pb', text: PB_ESCALATE_TEXT, escalate: q, q }]);
    }
    setBusy(false);
  };

  // Escalate an unanswered question to dispatch (cc Ronnie + Devin)
  const [escSent, setEscSent] = useStateF({});
  const escalateToHuman = async (question, idx) => {
    const phone = prompt('Drop your phone number and a real Clog Busterz plumber will text you back:');
    if (!phone) return;
    // ── LIVE DISPATCH BOARD — brain escalations are call-back-fast leads ──
    if (window.CB_DISPATCH) {
      window.CB_DISPATCH.sendLead({
        source: 'brain-escalation',
        name: 'Plumber\u2019s Brain visitor',
        phone: phone,
        notes: question,
        urgency: 'AI couldn\u2019t answer — call back fast',
      });
    }
    const FORM_ID = 'mbdekjeo'; // same Formspree ID as the site forms
    if (FORM_ID) {
      try {
        await fetch('https://formspree.io/f/' + FORM_ID, {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            _subject: "\ud83e\udde0 Plumber's Brain — question needs a human",
            _cc: 'ronniem@clogbusterzplumbing.com,devin@clogbusterzplumbing.com',
            question, phone, source: "Plumber's Brain escalation",
          }),
        });
      } catch (e) { console.warn(e); }
    }
    setEscSent(s => ({ ...s, [idx]: true }));
  };

  const quick = ["Relief valve dripping", "Do I need a permit?", "Smells like sewer", "Tankless maintenance"];

  return (
    <>
      {/* TEASER SECTION */}
      <section className="pb-section" id="brain" data-screen-label="brain">
        <div className="container">
          <div className="pb-hero">
            <div className="pb-hero-left">
              <div className="pb-tag"><span className="pb-pulse" />LIVE · BETA · IN-HOUSE BUILD</div>
              <h2 className="pb-h">
                MEET <span className="pb-glow">PLUMBER'S</span><br/>
                <span className="pb-glow2">BRAIN</span> AI.
              </h2>
              <p className="pb-sub">
                Source-backed plumbing answers built from Kentucky State Plumbing Code, manufacturer recommendations, and reviewed Clog Busterz field knowledge. If the source library does not cover it, Brain sends it to a real plumber instead of guessing.
              </p>
              <div className="pb-feats">
                <div className="pb-feat"><span className="pb-feat-n">01</span><span>Answers from code and manufacturer sources</span></div>
                <div className="pb-feat"><span className="pb-feat-n">02</span><span>Shows the source behind the answer</span></div>
                <div className="pb-feat"><span className="pb-feat-n">03</span><span>Routes unknown questions to a real plumber</span></div>
                <div className="pb-feat"><span className="pb-feat-n">04</span><span>Publishes approved answers for AI search</span></div>
              </div>
              <div className="pb-actions">
                <button className="btn btn-primary big-btn pb-cta" onClick={() => setOpen(true)}>
                  <span className="btn-line">TRY THE BETA</span>
                  <span className="btn-line big">ASK THE BRAIN →</span>
                </button>
                <a className="pb-hub-link" href="plumbers-brain/">READ THE ANSWER HUB →</a>
              </div>
            </div>
            <div className="pb-hero-right">
              <div className="pb-brain">
                <div className="pb-brain-ring" />
                <div className="pb-brain-ring pb-brain-ring-2" />
                <div className="pb-brain-ring pb-brain-ring-3" />
                <div className="pb-brain-core">
                  <div className="pb-brain-svg">
                    <svg viewBox="0 0 160 200" xmlns="http://www.w3.org/2000/svg" aria-label="Plunger">
                      {/* Wood handle — long vertical */}
                      <rect x="74" y="6" width="12" height="118" rx="3" fill="#c69257" stroke="#0e1a2b" strokeWidth="2.5"/>
                      <rect x="74" y="6" width="12" height="118" rx="3" fill="url(#woodGrain)" opacity="0.35"/>
                      {/* Handle cap */}
                      <ellipse cx="80" cy="8" rx="9" ry="4" fill="#a87642" stroke="#0e1a2b" strokeWidth="2"/>
                      {/* Metal collar where handle meets cup */}
                      <rect x="68" y="118" width="24" height="8" fill="#9aa6b8" stroke="#0e1a2b" strokeWidth="2"/>
                      {/* Plunger cup — red rubber, classic flared bell shape */}
                      <path d="M 28 130 Q 28 122 80 122 Q 132 122 132 130 Q 130 162 110 178 Q 95 188 80 188 Q 65 188 50 178 Q 30 162 28 130 Z" fill="#d94545" stroke="#0e1a2b" strokeWidth="2.5"/>
                      {/* Cup highlight */}
                      <path d="M 36 132 Q 50 128 80 128 Q 110 128 124 132" fill="none" stroke="#ff7878" strokeWidth="3" strokeLinecap="round" opacity="0.6"/>
                      {/* Cup ridge — horizontal seam */}
                      <path d="M 32 144 Q 50 152 80 152 Q 110 152 128 144" fill="none" stroke="#a82d2d" strokeWidth="2" opacity="0.7"/>
                      {/* Bottom dark shadow */}
                      <ellipse cx="80" cy="184" rx="32" ry="4" fill="#0e1a2b" opacity="0.25"/>
                      <defs>
                        <linearGradient id="woodGrain" x1="0" x2="1" y1="0" y2="0">
                          <stop offset="0" stopColor="#0e1a2b" stopOpacity="0"/>
                          <stop offset="0.5" stopColor="#0e1a2b" stopOpacity="0.6"/>
                          <stop offset="1" stopColor="#0e1a2b" stopOpacity="0"/>
                        </linearGradient>
                      </defs>
                    </svg>
                  </div>
                  <div className="pb-brain-label">PLUMBER'S<br/>BRAIN</div>
                  <div className="pb-brain-status"><span className="dot" />ONLINE · BETA</div>
                </div>
              </div>
              <div className="pb-receipt">
                <div className="pb-receipt-row"><span>MODEL</span><span className="v">PB-1 PREVIEW</span></div>
                <div className="pb-receipt-row"><span>KNOW-HOW</span><span className="v">3 GENERATIONS</span></div>
                <div className="pb-receipt-row"><span>GROUNDED IN</span><span className="v ok">KY CODE + SPECS</span></div>
                <div className="pb-receipt-row"><span>LANGUAGE</span><span className="v">PLAIN ENGLISH</span></div>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* FLOATING ASK-THE-BRAIN BUTTON */}
      {!open && fabShown && (
        <button className="pb-fab" onClick={() => setOpen(true)} aria-label="Ask the Brain">
          <svg className="pb-fab-svg" viewBox="0 0 160 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
            <rect x="74" y="6" width="12" height="118" rx="3" fill="#c69257" stroke="#0e1a2b" strokeWidth="2.5"/>
            <ellipse cx="80" cy="8" rx="9" ry="4" fill="#a87642" stroke="#0e1a2b" strokeWidth="2"/>
            <rect x="68" y="118" width="24" height="8" fill="#9aa6b8" stroke="#0e1a2b" strokeWidth="2"/>
            <path d="M 28 130 Q 28 122 80 122 Q 132 122 132 130 Q 130 162 110 178 Q 95 188 80 188 Q 65 188 50 178 Q 30 162 28 130 Z" fill="#d94545" stroke="#0e1a2b" strokeWidth="2.5"/>
            <path d="M 36 132 Q 50 128 80 128 Q 110 128 124 132" fill="none" stroke="#ff7878" strokeWidth="3" strokeLinecap="round" opacity="0.6"/>
          </svg>
          <span className="pb-fab-text">ASK<br/>THE BRAIN</span>
          <span className="pb-fab-pulse" />
        </button>
      )}

      {/* CHAT MODAL */}
      {open && (
        <div className="pb-modal" onClick={(e) => e.target === e.currentTarget && setOpen(false)}>
          <div className="pb-chat">
            <div className="pb-chat-head">
              <div className="pb-chat-title">
                <span className="pb-chat-icon" aria-hidden="true">
                  <svg viewBox="0 0 160 200" xmlns="http://www.w3.org/2000/svg">
                    <rect x="74" y="6" width="12" height="118" rx="3" fill="#c69257" stroke="#0e1a2b" strokeWidth="3"/>
                    <ellipse cx="80" cy="8" rx="9" ry="4" fill="#a87642" stroke="#0e1a2b" strokeWidth="2"/>
                    <rect x="68" y="118" width="24" height="8" fill="#9aa6b8" stroke="#0e1a2b" strokeWidth="2"/>
                    <path d="M 28 130 Q 28 122 80 122 Q 132 122 132 130 Q 130 162 110 178 Q 95 188 80 188 Q 65 188 50 178 Q 30 162 28 130 Z" fill="#d94545" stroke="#0e1a2b" strokeWidth="3"/>
                  </svg>
                </span>
                <div>
                  <div className="pb-chat-name">PLUMBER'S BRAIN</div>
                  <div className="pb-chat-sub"><span className="pb-pulse-tiny" />BETA · CLOG BUSTERZ</div>
                </div>
              </div>
              <button className="pb-chat-x" onClick={() => setOpen(false)}>×</button>
            </div>
            <div className="pb-chat-body" ref={scrollRef}>
              {msgs.map((m, i) => (
                <div key={i} className={`pb-msg pb-msg-${m.role}`}>
                  {m.role === 'pb' && <span className="pb-msg-tag">BRAIN</span>}
                  <div className="pb-msg-text">{m.text}</div>
                  {m.sources && m.sources.length > 0 && (
                    <div className="pb-sources">
                      {m.sources.map(source => (
                        <a key={source.id} href={source.url} target="_blank" rel="noopener noreferrer" className="pb-source">
                          {source.label}
                        </a>
                      ))}
                    </div>
                  )}
                  {m.escalate && (
                    <div className="pb-escalate">
                      {escSent[i] ? (
                        <div className="pb-esc-sent">✓ Sent — a real plumber will text you back shortly.</div>
                      ) : (
                        <>
                          <div className="pb-esc-label">I'd rather not guess on this one.</div>
                          <button className="pb-esc-btn" onClick={() => escalateToHuman(m.escalate, i)}>
                            📲 SEND TO A REAL PLUMBER →
                          </button>
                          <a href="tel:8594083382" className="pb-esc-call">or call 859-408-3382</a>
                        </>
                      )}
                    </div>
                  )}
                  {m.cta && (
                    <div className="pb-escalate">
                      {m.cta === 'urgent' && <div className="pb-esc-label">🚨 This one needs eyes on it fast — don't wait it out.</div>}
                      {m.cta === 'soft' && <div className="pb-esc-label">Want it done right? Get on the schedule.</div>}
                      {m.cta === 'gas' && <div className="pb-esc-label">🚨 We recommend calling 911 or the fire department first — then we can still get a crew out.</div>}
                      {m.cta === 'gas' && <a href="tel:911" className="pb-esc-btn">📞 CALL 911 / FIRE DEPT</a>}
                      {m.cta === 'urgent' && <a href="tel:8594083382" className="pb-esc-btn">📞 CALL NOW · 859-408-3382</a>}
                      <button className="pb-esc-btn" onClick={() => startInChatBooking(m.q, m.service, m.cta === 'gas' || m.cta === 'urgent')}>📅 BOOK A VISIT{(m.cta === 'gas' || m.cta === 'urgent') ? ' (EMERGENCY)' : ''} →</button>
                      {m.cta === 'gas' && <a href="tel:8594083382" className="pb-esc-call">or call us · 859-408-3382</a>}
                      {m.cta !== 'urgent' && m.cta !== 'gas' && <a href="tel:8594083382" className="pb-esc-call">or call 859-408-3382</a>}
                    </div>
                  )}
                  {/* Guided-flow interactive bits — only on the latest message, while idle */}
                  {i === msgs.length - 1 && !busy && (m.options || m.input) && (
                    <div className="pb-chat-quick" style={{ marginTop: 8, padding: 0, borderTop: 'none' }}>
                      {m.input === 'photo' && (
                        <label className="pb-quick" style={{ cursor: 'pointer' }}>
                          📷 Snap the data plate
                          <input type="file" accept="image/*" capture="environment" style={{ display: 'none' }}
                            onChange={e => { const f = e.target.files && e.target.files[0]; if (!f) return; resizeImage(f, 1600, 0.8).then(d => d && submitPlate(d)); }} />
                        </label>
                      )}
                      {(m.options || []).map(o => (
                        <button key={o.action} className="pb-quick" onClick={() => handleOption(o.action, o.label)}>{o.label}</button>
                      ))}
                    </div>
                  )}
                  {i === msgs.length - 1 && !busy && m.input === 'flood-form' && (
                    <PBFloodForm onSubmit={submitFloodLead} />
                  )}
                  {/* In-chat booking collector inputs */}
                  {i === msgs.length - 1 && !busy && m.input === 'book-name' && (
                    <PBTextInput placeholder="Your name" kind="name" onSubmit={bookName} />
                  )}
                  {i === msgs.length - 1 && !busy && m.input === 'book-phone' && (
                    <PBTextInput placeholder="Best phone number" kind="phone" onSubmit={bookPhone} />
                  )}
                  {i === msgs.length - 1 && !busy && m.input === 'book-address' && (
                    <PBTextInput placeholder="Street + city" kind="text" cta="REVIEW →" onSubmit={bookAddress} />
                  )}
                </div>
              ))}
              {busy && (
                <div className="pb-msg pb-msg-pb">
                  <span className="pb-msg-tag">BRAIN</span>
                  <div className="pb-msg-text"><span className="pb-typing"><span/><span/><span/></span></div>
                </div>
              )}
            </div>
            <div className="pb-chat-quick">
              {quick.map(q => (
                <button key={q} className="pb-quick" onClick={() => send(q)} disabled={busy}>{q}</button>
              ))}
            </div>
            <div className="pb-chat-input-row">
              <input
                className="pb-chat-input"
                placeholder="Describe your plumbing problem..."
                value={input}
                onChange={e => setInput(e.target.value)}
                onKeyDown={e => e.key === 'Enter' && send()}
                disabled={busy}
              />
              <button className="pb-chat-send" onClick={send} disabled={busy || !input.trim()}>SEND →</button>
            </div>
            <div className="pb-chat-foot">
              Plumber's Brain is AI and can make mistakes — please confirm anything important with a licensed plumber before you act. Kentucky code + manufacturer sources, plus real Clog Busterz pricing. Emergencies: <a href="tel:8594083382">859-408-3382</a>.
            </div>
          </div>
        </div>
      )}
    </>
  );
}
window.PlumberBrain = PlumberBrain;

// ============== 🥊 SECOND OPINION (with photos) ==============
// The buddy asked: "why didn't we do this like Plunger Pete — have it where they can upload and take
// photos." This is that. Camera capture OR upload (same resizeImage pipeline as the Brain plate
// scanner) of a competitor's quote, the leak, or the equipment plate → POST to the REAL engine
// (/api/second-opinion → lib/secondOpinion.js, source:'web') → honest verdict draft back, in CB's
// voice. No competitor name is ever shown; the office is pinged and follows up (no auto-contact).
// Opens from the hero "FREE second opinion" CTA via the window event 'cb-open-second-opinion'.
const SO_VERDICT = {
  BEAT:       { label: "WE CAN BEAT IT",  cls: 'so-beat',  ico: '💪' },
  FAIR:       { label: "THAT'S A FAIR PRICE", cls: 'so-fair', ico: '👍' },
  OVERPRICED: { label: "LOOKS OVERPRICED", cls: 'so-over', ico: '⚠️' },
  UNCLEAR:    { label: "LET'S TAKE A CLOSER LOOK", cls: 'so-unclear', ico: '🔍' },
};

function SecondOpinionModal() {
  const [open, setOpen] = useStateF(false);
  const [photos, setPhotos] = useStateF([]);   // data URLs (competitor quote / leak / plate)
  const [text, setText] = useStateF('');        // optional: pasted quote numbers
  const [name, setName] = useStateF('');
  const [phone, setPhone] = useStateF('');
  const [working, setWorking] = useStateF(false);
  const [busy, setBusy] = useStateF(false);
  const [result, setResult] = useStateF(null);  // { verdict, header, reply, followup, verdictShown }
  const [err, setErr] = useStateF('');

  useEffectF(() => {
    const onOpen = () => { setOpen(true); setResult(null); setErr(''); };
    window.addEventListener('cb-open-second-opinion', onOpen);
    return () => window.removeEventListener('cb-open-second-opinion', onOpen);
  }, []);

  const reset = () => { setPhotos([]); setText(''); setName(''); setPhone(''); setResult(null); setErr(''); setBusy(false); setWorking(false); };
  const close = () => { setOpen(false); };

  const addPhotos = async (files) => {
    setErr('');
    setWorking(true);
    const picked = Array.from(files).slice(0, 6 - photos.length);
    const out = [];
    for (const f of picked) { const d = await resizeImage(f, 1600, 0.8); if (d) out.push(d); }
    setPhotos((p) => [...p, ...out].slice(0, 6));
    setWorking(false);
  };
  const removePhoto = (idx) => setPhotos((p) => p.filter((_, i) => i !== idx));

  const canSubmit = (photos.length > 0 || text.trim().length > 3) && !busy && !working;

  const submit = async () => {
    if (!canSubmit) return;
    setBusy(true);
    setErr('');
    try {
      const r = await fetch(PB_SECOND_OPINION, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          photos, text: text.trim(), name: name.trim(), phone: phone.trim(),
          ref: (window.CB_DISPATCH && window.CB_DISPATCH.refCode) ? window.CB_DISPATCH.refCode() : '',
        }),
      });
      const j = await r.json();
      if (j && j.ok) { setResult(j); }
      else { setErr((j && j.error) || "I couldn't read that one clearly — try a sharper photo, or call us at 859-408-3382."); }
    } catch (_) {
      setErr("I couldn't reach our office just now — please try again, or call us at 859-408-3382 and we'll walk it through with you.");
    }
    setBusy(false);
  };

  if (!open) return null;
  const v = result && result.verdictShown && result.verdict ? SO_VERDICT[result.verdict] : null;

  return (
    <div className="so-overlay" onClick={(e) => { if (e.target === e.currentTarget) close(); }}>
      <div className="so-modal" role="dialog" aria-label="Free second opinion">
        <div className="so-head">
          <div className="so-head-title">
            <span className="so-head-ico" aria-hidden="true">🥊</span>
            <div>
              <div className="so-head-name">FREE SECOND OPINION</div>
              <div className="so-head-sub"><span className="pb-pulse-tiny" />HONEST READ · CLOG BUSTERZ</div>
            </div>
          </div>
          <button className="pb-chat-x" onClick={close} aria-label="Close">×</button>
        </div>

        <div className="so-body">
          {!result && (
            <>
              <p className="so-intro">
                Got a quote from another plumber, a leak you're worried about, or a water heater you're not sure on?
                <strong> Snap a photo or upload it</strong> — we'll give you a straight answer. Same read Plunger Pete gives,
                no pressure, and we <strong>never</strong> share your info outside Clog Busterz.
              </p>

              {/* Camera + upload — same pipeline as the Brain plate scanner */}
              <div className="so-uploads">
                <label className="so-drop">
                  <span className="so-drop-ico" aria-hidden="true">📷</span>
                  <span className="so-drop-t">Take a photo</span>
                  <input type="file" accept="image/*" capture="environment" multiple style={{ display: 'none' }}
                    onChange={(e) => { if (e.target.files && e.target.files.length) addPhotos(e.target.files); e.target.value = ''; }} />
                </label>
                <label className="so-drop">
                  <span className="so-drop-ico" aria-hidden="true">🖼️</span>
                  <span className="so-drop-t">Upload photos</span>
                  <input type="file" accept="image/*,application/pdf" multiple style={{ display: 'none' }}
                    onChange={(e) => { if (e.target.files && e.target.files.length) addPhotos(e.target.files); e.target.value = ''; }} />
                </label>
              </div>
              {working && <div className="so-hint">Getting your photos ready…</div>}
              {photos.length > 0 && (
                <div className="so-thumbs">
                  {photos.map((p, i) => (
                    <div key={i} className="so-thumb">
                      <img src={p} alt={`upload ${i + 1}`} />
                      <button className="so-thumb-x" onClick={() => removePhoto(i)} aria-label="Remove">×</button>
                    </div>
                  ))}
                </div>
              )}
              <div className="so-hint">{photos.length ? `${photos.length} of 6 attached` : 'Up to 6 photos — the other quote, the leak, or the silver data plate.'}</div>

              <details className="so-paste">
                <summary>Or paste the numbers instead</summary>
                <textarea className="so-textarea" rows={3} placeholder="e.g. Sump pump replacement — $2,450, plus a check valve line for $315, plus a $14.95/mo club fee…"
                  value={text} onChange={(e) => setText(e.target.value)} />
              </details>

              <div className="so-contact">
                <input className="pb-chat-input" placeholder="Your name (optional)" value={name} onChange={(e) => setName(e.target.value)} />
                <input className="pb-chat-input" placeholder="Phone for a free look (optional)" inputMode="tel" value={phone} onChange={(e) => setPhone(e.target.value)} />
              </div>

              {err && <div className="so-err">{err}</div>}

              <button className="so-submit" disabled={!canSubmit} onClick={submit}>
                {busy ? 'Reading it…' : '🥊 GET MY HONEST READ →'}
              </button>
              <div className="so-foot">
                It's an AI read from a real Clog Busterz plumber's playbook — a person confirms anything that matters before you act.
                We never post or share competitor names.
              </div>
            </>
          )}

          {result && (
            <div className="so-result">
              {v && <div className={`so-verdict ${v.cls}`}><span aria-hidden="true">{v.ico}</span> {v.label}</div>}
              {result.header && <p className="so-result-head">{result.header}</p>}
              <div className="so-result-body">{result.reply}</div>
              {result.followup && <div className="so-result-follow">{result.followup}</div>}
              <div className="so-result-actions">
                <a className="so-submit so-call" href="tel:8594083382">📞 CALL 859-408-3382</a>
                <button className="so-again" onClick={reset}>↻ Check another quote</button>
              </div>
              <div className="so-foot">
                A real Clog Busterz plumber reviews every second opinion — nobody gets auto-messaged, and your info stays with us.
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
window.SecondOpinionModal = SecondOpinionModal;
