// Business hub · seed listings from a link + note, engine auto-categorizes,
// operator claim invitations, claim tracking, onboarding/upsell campaigns.

const BIZ_CITIES = [];

// category taxonomy · seedable: operators can add categories and subcategories
const BIZ_TAXONOMY = {
  'Food & drink': ['Restaurant','Coffee','Catering','Bakery','Seafood'],
  'Beauty':       ['Barbershop','Salon','Beauty supply','Nails'],
  'Real estate':  ['Residential','Commercial','Property mgmt','Development'],
  'Finance':      ['Tax & accounting','Credit union','Financial planning','Lending'],
  'Health':       ['Clinic','Home care','Wellness','Dental','Therapy'],
  'Legal':        ['Personal injury','Criminal defense','Family','Estate','Business law'],
  'Auto & trade': ['Auto repair','HVAC','Plumbing','Electrical','Construction'],
  'Retail':       ['Bookstore','Florist','Clothing','Grocery','Gifts'],
};

const BIZ_SEED = [];

// --- engine: categorize from nothing but a link + note ---
function bizClassify(link, note){
  const s = (link+' '+note).toLowerCase();
  const subGuess =
    /barber|cuts/.test(s)          ? 'Barbershop'       :
    /coffee|caf/.test(s)           ? 'Coffee'           :
    /injury|accident/.test(s)      ? 'Personal injury'  :
    /criminal|defense/.test(s)     ? 'Criminal defense' :
    /tax|account/.test(s)          ? 'Tax & accounting' :
    /home care|caregiv/.test(s)    ? 'Home care'        :
    /book/.test(s)                 ? 'Bookstore'        : null;
  const cat =
    /coffee|kitchen|food|bbq|seafood|restaurant|bak|cater|grill|caf/.test(s) ? 'Food & drink'  :
    /barber|beauty|salon|hair|nail|glam|cuts/.test(s)                        ? 'Beauty'        :
    /real ?estate|realty|homes|property|broker/.test(s)                      ? 'Real estate'   :
    /tax|ledger|account|financ|credit|wealth|bank/.test(s)                   ? 'Finance'       :
    /health|care|clinic|wellness|dental|therap/.test(s)                      ? 'Health'        :
    /law|legal|attorney/.test(s)                                             ? 'Legal'         :
    /auto|repair|hvac|plumb|electric|construct/.test(s)                      ? 'Auto & trade'  : 'Retail';
  const city = BIZ_CITIES.find(c=>s.includes(c.toLowerCase())) || '';
  let host = link.replace(/^https?:\/\//,'').replace(/^www\./,'').split(/[\/?#]/)[0];
  const name = (host.split('.')[0]||'New business').replace(/[-_]/g,' ').replace(/\b\w/g, m=>m.toUpperCase());
  return { cat, sub: subGuess?[subGuess]:[], city, name, host };
}

// Revenue path · the ladder a seeded listing climbs
const REV_LADDER = [
  { k:'listed',   label:'Free listing',      rev:'$0' },
  { k:'claimed',  label:'Claimed · verified', rev:'$0' },
  { k:'member',   label:'TUEPAC member',      rev:'$25/yr' },
  { k:'featured', label:'Featured tier',      rev:'$240/yr' },
  { k:'premium',  label:'Premium tier',       rev:'$600/yr' },
  { k:'sponsor',  label:'Ad / newsletter spend', rev:'rate card' },
];
function rungIndex(b){
  if(b.rung!==undefined) return b.rung;
  if(b.status==='Claimed') return 1;
  return 0;
}

function BusinessHub({setRoute}){
  const [items, setItems] = React.useState(BIZ_SEED);
  const [tab, setTab]     = React.useState('All');
  const [sel, setSel]     = React.useState(null);
  const [seedLink, setSeedLink] = React.useState('');
  const [seedNote, setSeedNote] = React.useState('');
  const [nextNum, setNextNum]   = React.useState(133);
  const [taxonomy, setTaxonomy] = React.useState(BIZ_TAXONOMY);

  const biz = items.find(b=>b.id===sel) || items[0];
  const filt = tab==='All' ? items
    : tab==='Unclaimed' ? items.filter(b=>b.status==='Unclaimed'||b.status==='Enriching')
    : items.filter(b=>b.status===tab);

  function seed(){
    if(!seedLink.trim()) return;
    const id = 'BZ-'+nextNum;
    setNextNum(nextNum+1);
    const link = seedLink.trim(), note = seedNote.trim();
    const placeholder = { id, name:link.replace(/^https?:\/\//,'').replace(/^www\./,'').split(/[\/?#]/)[0], cat:' · ', sub:[], city:' · ', status:'Enriching', tier:'Free', operator:null, website:link.replace(/^https?:\/\//,'').replace(/^www\./,''), source:'Seeded', campaign:' · ', score:0, revenue:' · ', note: note || 'Seeded with link only.' };
    setItems(prev=>[placeholder, ...prev]);
    setSel(id); setSeedLink(''); setSeedNote('');
    setTimeout(()=>{
      const c = bizClassify(link, note);
      setItems(prev=>prev.map(b=>b.id===id ? {...b, name:c.name, cat:c.cat, sub:c.sub, city:c.city, website:c.host, status:'Unclaimed', score:60+Math.floor(Math.random()*25)} : b));
    }, 1600);
  }

  function sendInvite(id, op){
    setItems(prev=>prev.map(b=>b.id===id ? {...b, status:'Invited', operator:op, campaign:'Claim profile'} : b));
  }
  function markClaimed(id){
    setItems(prev=>prev.map(b=>b.id===id ? {...b, status:'Claimed', rung:Math.max(1, b.rung||0)} : b));
  }
  function setCampaign(id, campaign){
    setItems(prev=>prev.map(b=>b.id===id ? {...b, campaign} : b));
  }
  function setBizCat(id, cat){
    setTaxonomy(prev=> prev[cat] ? prev : {...prev, [cat]:[]});
    setItems(prev=>prev.map(b=>b.id===id ? {...b, cat, sub:[]} : b));
  }
  function toggleSub(id, sub){
    setItems(prev=>prev.map(b=>{
      if(b.id!==id) return b;
      const cur = b.sub||[];
      return {...b, sub: cur.includes(sub) ? cur.filter(x=>x!==sub) : [...cur, sub]};
    }));
  }
  function addSub(cat, sub, bizId){
    setTaxonomy(prev=>{
      const cur = prev[cat]||[];
      return cur.includes(sub) ? prev : {...prev, [cat]:[...cur, sub]};
    });
    toggleSub(bizId, sub);
  }

  function setRung(id, rung){
    setItems(prev=>prev.map(b=>b.id===id ? {...b, rung, tier: rung>=4?'Premium':rung>=3?'Featured':b.tier} : b));
  }

  const nClaimed = items.filter(b=>b.status==='Claimed').length;
  const nInvited = items.filter(b=>b.status==='Invited').length;

  return (
    <AdminShell route="biz" setRoute={setRoute} title="Business hub" breadcrumb="NETWORK · DIRECTORY + CLAIMS"
      actions={<>
        <button className="btn gh">Upload CSV</button>
        <button className="btn k">Directory preview ↗</button>
      </>}>

      {/* SEED BOX · a link and a note is all it takes */}
      <Card title="Seed a business" meta="a link + a note · the engine sorts and categorizes the rest"
        actions={<button className="btn g s" onClick={seed} style={{opacity:seedLink.trim()?1:.4}}>Seed →</button>} style={{marginBottom:18}}>
        <div className="cols3" style={{display:'grid',gridTemplateColumns:'1.1fr 1.6fr auto',gap:10,alignItems:'center'}}>
          <input value={seedLink} onChange={e=>setSeedLink(e.target.value)} onKeyDown={e=>{if(e.key==='Enter')seed();}}
            placeholder="qccuts.com · instagram.com/qccuts · google maps link"
            style={{border:'1px solid var(--rule-line)',padding:'10px 12px',background:'var(--bg)',outline:'none',fontSize:13,fontFamily:'var(--mono)',letterSpacing:'.02em',minWidth:0}}/>
          <input value={seedNote} onChange={e=>setSeedNote(e.target.value)} onKeyDown={e=>{if(e.key==='Enter')seed();}}
            placeholder="note (optional) · e.g. family barbershop, 40 years in the neighborhood"
            style={{border:'1px solid var(--rule-line)',padding:'10px 12px',background:'var(--bg)',outline:'none',fontSize:13,fontFamily:'var(--sans)',minWidth:0}}/>
          <div style={{display:'flex',gap:6,flexWrap:'wrap'}}>
            <Pill k="info">CATEGORY · AUTO</Pill>
            <Pill k="warn">CITY · AUTO</Pill>
          </div>
        </div>
        <div className="mono" style={{fontSize:9.5,color:'var(--mute)',letterSpacing:'.1em',marginTop:8}}>ENGINE PULLS NAME · CATEGORY · LOCATION · HOURS · SOCIALS FROM THE LINK · INVITE THE OPERATOR WHEN READY</div>
      </Card>

      {/* STATS */}
      <div className="split-4" style={{marginBottom:18}}>
        <Stat n={items.length} l="Directory listings" d={null}/>
        <Stat n={items.length?`${Math.round((nClaimed/items.length)*100)}%`:'0%'} l="Claimed" d={`${nClaimed} of ${items.length} · goal 60%`}/>
        <Stat n={nInvited} l="Invites outstanding" d={null}/>
        <Stat n="$0" l="Upsell pipeline · yr" d={null}/>
      </div>

      {/* DIRECTORY + DETAIL */}
      <div className="lay2" style={{display:'grid',gridTemplateColumns:'1.5fr 1.1fr',gap:18,alignItems:'flex-start'}}>

        <Card title="Directory" meta={`${filt.length} listings`}
          actions={<Seg value={tab} onChange={setTab} options={['All','Unclaimed','Invited','Claimed']}/>}>
          <table className="tbl" style={{marginLeft:-14,marginRight:-14,width:'calc(100% + 28px)'}}>
            <thead><tr><th>BUSINESS</th><th>CATEGORY</th><th>CITY</th><th>STATUS</th><th>TIER</th><th className="r">FIT</th></tr></thead>
            <tbody>
              {!filt.length && <tr><td colSpan="6"><span className="mono" style={{fontSize:9.5,letterSpacing:'.1em',color:'var(--mute)'}}>NO LISTINGS YET · SEED THE FIRST ONE ABOVE</span></td></tr>}
              {filt.map(b=>(
                <tr key={b.id} className={b.id===sel?'sel':''} onClick={()=>setSel(b.id)}>
                  <td>
                    <div style={{fontSize:12.5,fontWeight:600}}>{b.name}</div>
                    <div className="mono" style={{fontSize:9.5,color:'var(--mute)',letterSpacing:'.04em'}}>{b.website.toUpperCase()}</div>
                  </td>
                  <td>
                    <div className="mono" style={{fontSize:10.5,letterSpacing:'.04em'}}>{b.cat}</div>
                    {(b.sub||[]).length>0 && <div className="mono" style={{fontSize:9,color:'var(--mute)',letterSpacing:'.04em',marginTop:2}}>{b.sub.join(' · ').toUpperCase()}</div>}
                  </td>
                  <td className="mono" style={{fontSize:10.5,letterSpacing:'.04em'}}>{b.city}</td>
                  <td><Pill k={b.status==='Claimed'?'live':b.status==='Invited'?'warn':b.status==='Enriching'?'info':'muted'}>{b.status==='Enriching'?'Sorting…':b.status}</Pill></td>
                  <td className="mono" style={{fontSize:10,letterSpacing:'.06em',color:b.tier==='Premium'?'var(--gold-2)':b.tier==='Featured'?'var(--navy)':'var(--mute)'}}>{b.tier.toUpperCase()}</td>
                  <td className="r">{b.status==='Enriching'?<span className="mono" style={{fontSize:10,color:'var(--mute)'}}> · </span>:<Score n={b.score}/>}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>

        {biz ? <BizDetail biz={biz} onInvite={sendInvite} onClaim={markClaimed} onCampaign={setCampaign}
          taxonomy={taxonomy} onSetCat={setBizCat} onToggleSub={toggleSub} onAddSub={addSub} onRung={setRung}/>
        : <Card title="Listing detail" meta="none selected"><div className="mono" style={{padding:'14px 0',fontSize:9.5,letterSpacing:'.1em',color:'var(--mute)'}}>SEED A BUSINESS · THE ENGINE SORTS IT AND THE DETAIL OPENS HERE</div></Card>}
      </div>

      {/* CAMPAIGNS */}
      <Card title="Business campaigns" meta="onboarding + upsell"
        actions={<button className="btn gh s">+ New campaign</button>} style={{marginTop:18}}>
        <table className="tbl" style={{marginLeft:-14,marginRight:-14,width:'calc(100% + 28px)'}}>
          <thead><tr><th>CAMPAIGN</th><th>TARGET</th><th className="r">IN SEQUENCE</th><th className="r">OPEN</th><th className="r">REPLY</th><th className="r">CONV</th><th>OWNER</th></tr></thead>
          <tbody>
            {[
              ['Claim profile',           'Unclaimed listings',        0, '·', '·', '·', 'MW'],
              ['Directory → Advertiser',  'Claimed · high traffic',    0, '·', '·', '·', 'MW'],
              ['Featured upgrade',        'Claimed · free tier',       0, '·', '·', '·', 'MW'],
              ['Newsletter sponsor',      'Featured + premium',        0, '·', '·', '·', 'MW'],
              ['Spotlight rotation',      'New claims · first 30 days',0, '·', '·', '·', 'MW'],
            ].map((r,i)=>(
              <tr key={i}>
                <td style={{fontSize:12.5,fontWeight:600}}>{r[0]}</td>
                <td className="mono" style={{fontSize:10.5,color:'var(--ink-2)',letterSpacing:'.04em'}}>{r[1]}</td>
                <td className="r num">{r[2]}</td>
                <td className="r num" style={{color:'var(--navy)',fontWeight:600}}>{r[3]}</td>
                <td className="r num" style={{color:'var(--gold-2)',fontWeight:600}}>{r[4]}</td>
                <td className="r num" style={{color:'var(--green)',fontWeight:700}}>{r[5]}</td>
                <td><span className="mono" style={{fontSize:10,color:'var(--navy)',letterSpacing:'.08em',fontWeight:600}}>{r[6]}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>
    </AdminShell>
  );
}

// ---------- detail panel ----------
function BizDetail({biz, onInvite, onClaim, onCampaign, taxonomy, onSetCat, onToggleSub, onAddSub, onRung}){
  return (
    <div style={{display:'flex',flexDirection:'column',gap:18,minWidth:0}}>
      <RevenuePath biz={biz} onRung={onRung}/>
      <Card title={biz.name} meta={`${biz.id} · ${biz.source.toLowerCase()}`}
        actions={biz.status==='Claimed'
          ? <button className="btn gh s">View listing ↗</button>
          : biz.status==='Invited'
            ? <button className="btn gr s" onClick={()=>onClaim(biz.id)}>Mark claimed ✓</button>
            : null}>
        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginBottom:14}}>
          <BizKV l="City"     v={biz.city}/>
          <BizKV l="Status"   v={biz.status}/>
          <BizKV l="Website"  v={biz.website}/>
          <BizKV l="Tier"     v={biz.tier}/>
        </div>

        {biz.status!=='Enriching' && (
          <CatEditor biz={biz} taxonomy={taxonomy} onSetCat={onSetCat} onToggleSub={onToggleSub} onAddSub={onAddSub}/>
        )}

        <div className="eyebrow" style={{marginTop:14}}>SEED NOTE</div>
        <div style={{fontSize:13,marginTop:6,padding:'10px 12px',background:'var(--canvas)',border:'1px solid var(--rule-line)',lineHeight:1.45}}>{biz.note}</div>

        {biz.status==='Enriching' && (
          <div className="mono" style={{marginTop:14,fontSize:10,letterSpacing:'.14em',color:'var(--mute)',textTransform:'uppercase'}}>Engine is sorting + categorizing from the link…</div>
        )}

        {biz.status!=='Enriching' && <>
          <div style={{height:1,background:'var(--rule-line)',margin:'14px 0'}}></div>
          <div className="eyebrow" style={{marginBottom:8}}>ENRICHMENT · AUTO</div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'4px 14px'}}>
            {[
              ['Name', biz.name, 'ok'],
              ['Category', biz.cat, 'ok'],
              ['Location', biz.city||'·', biz.city?'ok':'warn'],
              ['Hours', biz.status==='Claimed'?'confirmed':'scraped', biz.status==='Claimed'?'ok':'warn'],
              ['Socials', '2 found', 'ok'],
              ['Photos', biz.status==='Claimed'?'operator-supplied':'placeholder', biz.status==='Claimed'?'ok':'warn'],
              ['Black-owned verify', biz.status==='Claimed'?'operator-attested':'community-sourced', biz.status==='Claimed'?'ok':'warn'],
              ['Brand safety', 'cleared', 'ok'],
            ].map(([k,v,c])=>(
              <div key={k} style={{display:'grid',gridTemplateColumns:'auto 1fr',gap:8,padding:'4px 0',alignItems:'baseline'}}>
                <span style={{color:c==='ok'?'var(--green)':'var(--gold-2)',fontSize:11}}>{c==='ok'?'✓':'!'}</span>
                <span style={{fontSize:11.5}}><span style={{color:'var(--mute)'}}>{k}:</span> <b>{v}</b></span>
              </div>
            ))}
          </div>
        </>}
      </Card>

      {biz.status==='Unclaimed' && <InviteForm biz={biz} onInvite={onInvite}/>}
      {biz.status==='Invited'   && <InviteSent biz={biz}/>}
      {biz.status==='Claimed'   && <UpsellCard biz={biz} onCampaign={onCampaign}/>}
    </div>
  );
}

// ---------- revenue path · which rung of the ladder this operator has reached ----------
function RevenuePath({biz, onRung}){
  const cur = rungIndex(biz);
  return (
    <Card title="Revenue path" meta={REV_LADDER[cur].label.toLowerCase()}>
      <div style={{display:'flex',flexDirection:'column'}}>
        {REV_LADDER.map((r,i)=>{
          const done = i<=cur, next = i===cur+1;
          return (
            <div key={r.k} onClick={()=>onRung(biz.id, i)}
              style={{display:'grid',gridTemplateColumns:'auto 1fr auto',gap:10,padding:'6px 0',alignItems:'center',cursor:'default',
                borderBottom:i===REV_LADDER.length-1?'none':'1px solid var(--rule-line)',opacity:done?1:next?.85:.5}}>
              <span style={{width:16,height:16,display:'flex',alignItems:'center',justifyContent:'center',fontSize:9.5,fontWeight:700,
                background:done?'var(--green)':next?'var(--bg)':'var(--canvas)',color:done?'var(--ivory)':'var(--mute)',
                border:'1px solid '+(done?'var(--green)':next?'var(--gold-2)':'var(--rule-line)')}}>{done?'✓':i+1}</span>
              <span style={{fontSize:12,fontWeight:done||next?600:400}}>{r.label}{next && <span className="mono" style={{fontSize:8.5,letterSpacing:'.1em',color:'var(--gold-2)',marginLeft:8}}>NEXT</span>}</span>
              <span className="mono" style={{fontSize:10,letterSpacing:'.04em',color:done?'var(--green)':'var(--mute)'}}>{r.rev}</span>
            </div>
          );
        })}
      </div>
      <div className="mono" style={{fontSize:9,letterSpacing:'.08em',color:'var(--mute)',marginTop:8}}>CLICK A RUNG TO MARK PROGRESS · TIER UPDATES WITH IT</div>
    </Card>
  );
}

// ---------- category editor: pick or seed a category, refine with subcategories ----------
function CatEditor({biz, taxonomy, onSetCat, onToggleSub, onAddSub}){
  const [seeding, setSeeding] = React.useState(false);
  const [newCat, setNewCat]   = React.useState('');
  const [newSub, setNewSub]   = React.useState('');
  React.useEffect(()=>{ setSeeding(false); setNewCat(''); setNewSub(''); }, [biz.id]);
  const subs = taxonomy[biz.cat] || [];
  const sel  = biz.sub || [];

  function commitCat(){
    const c = newCat.trim();
    if(!c) return;
    onSetCat(biz.id, c); setSeeding(false); setNewCat('');
  }
  function commitSub(){
    const s = newSub.trim();
    if(!s) return;
    onAddSub(biz.cat, s, biz.id); setNewSub('');
  }

  return (
    <div style={{border:'1px solid var(--rule-line)',background:'var(--canvas)',padding:'10px 12px'}}>
      <div style={{display:'flex',alignItems:'center',gap:8,flexWrap:'wrap'}}>
        <span className="eyebrow">CATEGORY</span>
        {!seeding ? (
          <>
            <select value={taxonomy[biz.cat]?biz.cat:''} onChange={e=>onSetCat(biz.id, e.target.value)}
              style={{padding:'5px 8px',border:'1px solid var(--rule-line)',background:'var(--bg)',fontSize:12,fontFamily:'var(--sans)',outline:'none'}}>
              {!taxonomy[biz.cat] && <option value=""> · </option>}
              {Object.keys(taxonomy).map(c=><option key={c} value={c}>{c}</option>)}
            </select>
            <button className="btn gh s" onClick={()=>setSeeding(true)}>+ Seed new</button>
          </>
        ) : (
          <span style={{display:'flex',gap:6,alignItems:'center'}}>
            <input autoFocus value={newCat} onChange={e=>setNewCat(e.target.value)} onKeyDown={e=>{if(e.key==='Enter')commitCat(); if(e.key==='Escape')setSeeding(false);}}
              placeholder="new category" style={{padding:'5px 8px',border:'1px solid var(--rule-line)',background:'var(--bg)',fontSize:12,outline:'none',width:150}}/>
            <button className="btn k s" onClick={commitCat} style={{opacity:newCat.trim()?1:.4}}>Add</button>
            <button className="btn gh s" onClick={()=>setSeeding(false)}>×</button>
          </span>
        )}
      </div>

      <div className="eyebrow" style={{margin:'10px 0 6px'}}>SUBCATEGORY · {sel.length?sel.join(' · ').toUpperCase():'NONE · PICK OR ADD'}</div>
      <div style={{display:'flex',flexWrap:'wrap',gap:5,alignItems:'center'}}>
        {subs.map(s=>{
          const on = sel.includes(s);
          return (
            <button key={s} onClick={()=>onToggleSub(biz.id, s)}
              style={{padding:'3px 9px',fontFamily:'var(--mono)',fontSize:9.5,letterSpacing:'.08em',textTransform:'uppercase',cursor:'default',
                border:'1px solid '+(on?'var(--black)':'var(--rule-line)'),background:on?'var(--black)':'var(--bg)',color:on?'var(--ivory)':'var(--ink-2)'}}>
              {on?'✓ ':''}{s}
            </button>
          );
        })}
        <span style={{display:'inline-flex',border:'1px solid var(--rule-line)',background:'var(--bg)'}}>
          <input value={newSub} onChange={e=>setNewSub(e.target.value)} onKeyDown={e=>{if(e.key==='Enter')commitSub();}}
            placeholder="+ add · e.g. PI, criminal" style={{border:0,outline:'none',background:'transparent',padding:'3px 8px',fontSize:11,fontFamily:'var(--sans)',width:130}}/>
          {newSub.trim() && <button className="btn k s" onClick={commitSub} style={{border:0}}>↵</button>}
        </span>
      </div>
    </div>
  );
}

function BizKV({l,v}){
  return <div style={{padding:'4px 0'}}><div className="mono" style={{fontSize:9,color:'var(--mute)',letterSpacing:'.14em',textTransform:'uppercase'}}>{l}</div><div style={{fontSize:12,marginTop:2,fontWeight:500}}>{v}</div></div>;
}

const bizInp = {width:'100%',padding:'8px 10px',border:'1px solid var(--rule-line)',background:'var(--bg)',fontSize:12.5,fontFamily:'var(--sans)',outline:'none',display:'block'};

// ---------- invite the operator: name, number, email, note, website, location ----------
function InviteForm({biz, onInvite}){
  const [name, setName]   = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [note, setNote]   = React.useState('');
  const [site, setSite]   = React.useState(biz.website);
  const [loc, setLoc]     = React.useState(biz.city===' · '?'':biz.city);
  React.useEffect(()=>{ setSite(biz.website); setLoc(biz.city===' · '?'':biz.city); setName(''); setPhone(''); setEmail(''); setNote(''); }, [biz.id]);
  const ready = name.trim() && (email.trim() || phone.trim());

  return (
    <Card title="Invite the operator" meta="starts the claim sequence · no public labeling without their say"
      actions={<div style={{display:'flex',gap:8}}>
        {/\S+@\S+\.\S+/.test(email) && <a className="btn k s" style={{textDecoration:'none',opacity:ready?1:.4}}
          href={'mailto:'+email.trim()+'?subject='+encodeURIComponent((biz.name||'Your business')+' · customers on TUEPAC are searching for you')+'&body='+encodeURIComponent('Hi'+(name.trim()?' '+name.trim():'')+',\n\nTUEPAC members in '+(loc.trim()||'your area')+' search our directory for exactly what '+(biz.name||'your business')+' does. We hold a listing for you and would like you to claim it.\n\nWhat claiming gets you:\n· You appear when our members search your category and city\n· Direct calls and bookings, we route the customer to you\n· You control the listing: your name, your brand, your words. We never label your business; the directory is where customers choose to shop the network.\n\nClaim takes 3 minutes: https://tuepac.com/Join.html\n\nQuestions, just reply.\n\nThe United Economic Professional Advancement Coalition')}
          onClick={()=>ready && onInvite(biz.id,{name:name.trim(),email:email.trim(),phone:phone.trim(),note:note.trim()})}>Open onboarding email ✉</a>}
        <button className="btn g s" onClick={()=>ready && onInvite(biz.id,{name:name.trim(),email:email.trim(),phone:phone.trim(),note:note.trim()})} style={{opacity:ready?1:.4}}>Send claim invite →</button>
      </div>}>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'10px 12px'}}>
        <div><div className="eyebrow" style={{marginBottom:5}}>NAME</div><input value={name} onChange={e=>setName(e.target.value)} placeholder="operator / owner" style={bizInp}/></div>
        <div><div className="eyebrow" style={{marginBottom:5}}>NUMBER</div><input value={phone} onChange={e=>setPhone(e.target.value)} placeholder="(704) 555-0100" style={bizInp}/></div>
        <div><div className="eyebrow" style={{marginBottom:5}}>EMAIL</div><input value={email} onChange={e=>setEmail(e.target.value)} placeholder="owner@business.com" style={bizInp}/></div>
        <div><div className="eyebrow" style={{marginBottom:5}}>LOCATION</div><input value={loc} onChange={e=>setLoc(e.target.value)} placeholder="City, ST" style={bizInp}/></div>
        <div style={{gridColumn:'1 / -1'}}><div className="eyebrow" style={{marginBottom:5}}>WEBSITE</div><input value={site} onChange={e=>setSite(e.target.value)} style={{...bizInp,fontFamily:'var(--mono)',fontSize:11.5}}/></div>
        <div style={{gridColumn:'1 / -1'}}><div className="eyebrow" style={{marginBottom:5}}>NOTE</div><textarea value={note} onChange={e=>setNote(e.target.value)} placeholder="personal line for the invite · e.g. saw the shop featured in the Post last month" style={{...bizInp,minHeight:52,resize:'vertical'}}></textarea></div>
      </div>
      <div className="mono" style={{fontSize:9.5,color:'var(--mute)',letterSpacing:'.1em',marginTop:10}}>NAME + EMAIL OR NUMBER IS ENOUGH · TEMPLATE T-BIZ-01 FILLS THE REST</div>
    </Card>
  );
}

function InviteSent({biz}){
  const op = biz.operator || {};
  return (
    <Card title="Claim invite · sent" meta="sequence day 2"
      actions={<button className="btn gh s">Resend</button>}>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginBottom:12}}>
        <BizKV l="Operator" v={op.name||' · '}/>
        <BizKV l="Number"   v={op.phone||' · '}/>
        <BizKV l="Email"    v={op.email||' · '}/>
        <BizKV l="Campaign" v={biz.campaign}/>
      </div>
      <div style={{display:'flex',flexDirection:'column'}}>
        {[
          ['Day 0','Seeded','Listing created from link + note','done'],
          ['Day 1','Sorted','Engine categorized · placed in directory','done'],
          ['Day 2','Invited','Claim invite sent · T-BIZ-01','done'],
          ['Day 4','Opened','Open + click tracking','queued'],
          ['Day 7','Claimed','Operator verifies · listing goes live as claimed','queued'],
          ['Day 30','Upsell','Enters Featured-upgrade campaign','queued'],
        ].map(([d,s,n,c],i)=>(
          <div key={i} style={{display:'grid',gridTemplateColumns:'48px 70px 1fr auto',gap:10,padding:'6px 0',borderBottom:i===5?'none':'1px solid var(--rule-line)',alignItems:'center',opacity:c==='done'?1:.55}}>
            <span className="mono" style={{fontSize:10,color:'var(--mute)',letterSpacing:'.04em'}}>{d}</span>
            <span className="mono" style={{fontSize:10,letterSpacing:'.06em',color:c==='done'?'var(--green)':'var(--mute)'}}>{s.toUpperCase()}</span>
            <span style={{fontSize:11.5}}>{n}</span>
            <span style={{width:14,textAlign:'center',color:c==='done'?'var(--green)':'var(--mute)',fontSize:13}}>{c==='done'?'✓':'○'}</span>
          </div>
        ))}
      </div>
    </Card>
  );
}

function UpsellCard({biz, onCampaign}){
  const op = biz.operator || {};
  const opts = ['Directory → Advertiser','Featured upgrade','Newsletter sponsor','Spotlight rotation'];
  return (
    <Card title="Claimed · next move" meta={`operator · ${op.name||' · '}`}>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginBottom:12}}>
        <BizKV l="Operator" v={op.name||' · '}/>
        <BizKV l="Number"   v={op.phone||' · '}/>
        <BizKV l="Email"    v={op.email||' · '}/>
        <BizKV l="Campaign" v={biz.campaign}/>
      </div>
      <div className="eyebrow" style={{marginBottom:8}}>ASSIGN UPSELL CAMPAIGN</div>
      <div style={{display:'flex',flexWrap:'wrap',gap:6}}>
        {opts.map(o=>(
          <button key={o} className={'btn s '+(biz.campaign===o?'k':'gh')} onClick={()=>onCampaign(biz.id,o)}>{o}</button>
        ))}
      </div>
    </Card>
  );
}

window.BusinessHub = BusinessHub;
