// ============ Recipe Coverage Report ============
// ตอบโจทย์ Phase 1 Success Criteria: "เจ้าของรู้ต้นทุนจริงและ GP ทุกเมนู"
// แสดงว่าเมนูที่กำลังขายเมนูไหน "ครบ" (มีสูตร + ตั้งราคา → คำนวณ GP ได้)
// และเมนูไหนยัง "ขาด" อะไร เพื่อใช้เป็น to-do list ปิดช่องว่างข้อมูล

function coverageRows(db){
  return (db.menus||[]).map(m=>{
    const e = menuEconomics(db, m);
    const hasRecipe = !!e.hasRecipe;
    const hasCost = e.total > 0;
    const hasPriceStore = (+m.priceStore||0) > 0;
    const gpKnown = hasRecipe && hasPriceStore;
    // ขาดอะไรบ้าง — เรียงตามความสำคัญ (สูตรก่อน แล้วราคา)
    const gaps = [];
    if(!hasRecipe) gaps.push('สูตร');
    if(!hasPriceStore) gaps.push('ราคาหน้าร้าน');
    if(hasRecipe && !hasCost) gaps.push('ต้นทุน (สูตรมีแต่คิดต้นทุนไม่ได้)');
    const complete = hasRecipe && hasCost && hasPriceStore;
    return { m, e, hasRecipe, hasCost, hasPriceStore, gpKnown, gaps, complete,
      gpPct: gpKnown ? e.gpStorePct : null };
  });
}

function RecipeCoveragePage({ go }){
  const { db, setDb, settings, flash, logActivity } = useData();
  const [scope, setScope] = React.useState('selling'); // selling | all
  const [search, setSearch] = React.useState('');
  const [batchBusy, setBatchBusy] = React.useState(false);
  const targetGP = Number(settings.estGP) || 0.65;

  // Apply local heuristic draft for a single menu
  const draftOne = React.useCallback((m) => {
    if (!window.aiRecipeDraft) { flash('ยังโหลด AI module ไม่สำเร็จ', 'err'); return; }
    const draft = window.aiRecipeDraft(m, db);
    if (!draft.lines.length && !draft.pkgLines.length) {
      flash(`${m.name}: ยังจับคู่วัตถุดิบไม่ได้ — เพิ่มวัตถุดิบก่อน`, 'err'); return;
    }
    setDb(prev => {
      const base = draft.lines.map(l => ({ menuId: m.id, ingId: l.item.id, qty: +l.qty||0, unit: l.item.unit||l.unit||'', costPerUnit: +l.item.costPerUnit||0, lineCost: (+l.qty||0)*(+l.item.costPerUnit||0) }));
      const pkg = draft.pkgLines.map(l => ({ menuId: m.id, pkgId: l.item.id, qty: +l.qty||0, unit: l.item.unit||'ชิ้น', costPerPiece: +l.item.costPerPiece||0, lineCost: (+l.qty||0)*(+l.item.costPerPiece||0) }));
      return { ...prev,
        recipeBase: [...prev.recipeBase.filter(r => r.menuId !== m.id), ...base],
        recipePackage: [...prev.recipePackage.filter(r => r.menuId !== m.id), ...pkg],
      };
    });
    flash(`สร้างสูตรร่างให้ ${m.name} แล้ว`);
  }, [db, setDb, flash]);

  // Batch: apply local drafts for ALL menus missing recipes in current scope
  const batchDraft = React.useCallback(() => {
    if (!window.aiRecipeDraft) { flash('ยังโหลด AI module ไม่สำเร็จ', 'err'); return; }
    const rows = coverageRows(db);
    const targets = (scope === 'selling' ? rows.filter(r => r.m.status === 'ขาย') : rows).filter(r => !r.hasRecipe);
    if (!targets.length) { flash('ทุกเมนูมีสูตรแล้ว'); return; }
    setBatchBusy(true);
    let created = 0, skipped = 0;
    const newBase = [], newPkg = [], menuIds = new Set();
    targets.forEach(({ m }) => {
      const draft = window.aiRecipeDraft(m, db);
      if (draft.lines.length || draft.pkgLines.length) {
        created++;
        menuIds.add(m.id);
        draft.lines.forEach(l => newBase.push({ menuId: m.id, ingId: l.item.id, qty: +l.qty||0, unit: l.item.unit||l.unit||'', costPerUnit: +l.item.costPerUnit||0, lineCost: (+l.qty||0)*(+l.item.costPerUnit||0) }));
        draft.pkgLines.forEach(l => newPkg.push({ menuId: m.id, pkgId: l.item.id, qty: +l.qty||0, unit: l.item.unit||'ชิ้น', costPerPiece: +l.item.costPerPiece||0, lineCost: (+l.qty||0)*(+l.item.costPerPiece||0) }));
      } else { skipped++; }
    });
    if (!created) { flash('ยังจับคู่วัตถุดิบไม่ได้เลย — เพิ่มวัตถุดิบหลัก (กาแฟ/นม/แป้ง) ก่อน', 'err'); setBatchBusy(false); return; }
    setDb(prev => ({
      ...prev,
      recipeBase: [...prev.recipeBase.filter(r => !menuIds.has(r.menuId)), ...newBase],
      recipePackage: [...prev.recipePackage.filter(r => !menuIds.has(r.menuId)), ...newPkg],
    }));
    if (logActivity) logActivity('recipe.batch_draft', { note: `batch draft ${created} menus` });
    flash(`สร้างสูตรร่างให้ ${created} เมนูแล้ว${skipped ? ` · ${skipped} เมนูไม่มีวัตถุดิบที่ตรงกัน` : ''}`);
    setBatchBusy(false);
  }, [db, setDb, scope, flash, logActivity]);

  const all = React.useMemo(()=>coverageRows(db), [db.menus, db.recipeBase, db.recipeBatch, db.recipePackage, db.recipeOption, db.ingredients, db.packages, db.batchRecipes, db.batchRecipeLines]);
  const scoped = scope==='selling' ? all.filter(r=>r.m.status==='ขาย') : all;

  const total = scoped.length;
  const completeCount = scoped.filter(r=>r.complete).length;
  const noRecipe = scoped.filter(r=>!r.hasRecipe).length;
  const noPrice = scoped.filter(r=>r.hasRecipe && !r.hasPriceStore).length;
  const lowGP = scoped.filter(r=>r.complete && r.gpPct!=null && r.gpPct < targetGP - 0.1).length;
  const priceable = scoped.filter(r=>r.hasRecipe && r.hasCost && !r.hasPriceStore).length;
  const coverage = total>0 ? completeCount/total : 0;

  // ตั้งราคาแนะนำให้เมนูที่มีต้นทุนแต่ยังไม่มีราคา (ปัดขึ้นทีละ ฿5)
  const bulkAutoPrice = React.useCallback(() => {
    const targets = scoped.filter(r => r.hasRecipe && r.hasCost && !r.hasPriceStore);
    if (!targets.length) { flash('ไม่มีเมนูที่พร้อมตั้งราคา'); return; }
    const updates = {};
    targets.forEach(({m, e}) => {
      const rec = Math.ceil(e.total / (1 - targetGP) / 5) * 5;
      if (rec > 0) updates[m.id] = rec;
    });
    if (!Object.keys(updates).length) { flash('คำนวณราคาไม่ได้ เพราะต้นทุนเป็น 0', 'err'); return; }
    const summaryEvt = { id:'BEV'+Date.now().toString(36)+Math.random().toString(36).slice(2,5), type:'price_change', date:new Date().toISOString().slice(0,10), title:`ตั้งราคาแนะนำ ${Object.keys(updates).length} เมนู (Coverage)`, description:`GP เป้า ${(targetGP*100).toFixed(0)}% · ปัดขึ้นทีละ ฿5`, impact:'positive', createdAt:new Date().toISOString() };
    setDb(prev => ({
      ...prev,
      menus: prev.menus.map(m => updates[m.id] ? {...m, priceStore: updates[m.id]} : m),
      businessEvents: [summaryEvt, ...(prev.businessEvents||[])],
    }));
    if (logActivity) logActivity('pricing.bulk_auto', { note: `auto-price ${Object.keys(updates).length} menus` });
    flash(`ตั้งราคาแนะนำให้ ${Object.keys(updates).length} เมนูแล้ว · บันทึก Business Event ด้วย`);
  }, [scoped, targetGP, setDb, flash, logActivity]);

  // ตั้งราคาแนะนำให้เมนูเดียว
  const priceOne = React.useCallback((m, e) => {
    const rec = Math.ceil(e.total / (1 - targetGP) / 5) * 5;
    if (!rec) { flash('คำนวณราคาไม่ได้ เพราะต้นทุนเป็น 0', 'err'); return; }
    const evt = { id:'BEV'+Date.now().toString(36)+Math.random().toString(36).slice(2,5), type:'price_change', date:new Date().toISOString().slice(0,10), title:`ตั้งราคา ${m.name} = ฿${rec}`, description:`ราคาแนะนำจากต้นทุน ฿${e.total.toFixed(2)} · GP ${((1-e.total/rec)*100).toFixed(0)}%`, impact:'neutral', linkedMenuId:m.id, createdAt:new Date().toISOString() };
    setDb(prev => ({ ...prev, menus: prev.menus.map(x => x.id===m.id ? {...x,priceStore:rec} : x), businessEvents: [evt,...(prev.businessEvents||[])] }));
    flash(`ตั้งราคา ${m.name} = ฿${rec}`);
  }, [targetGP, setDb, flash]);

  // รายการที่ยังขาดข้อมูล — เรียง: ไม่มีสูตร > ไม่มีราคา > GP ต่ำ
  const gapList = scoped
    .filter(r=>!r.complete || (r.gpPct!=null && r.gpPct < targetGP - 0.1))
    .filter(r=>{
      if(!search.trim()) return true;
      const q = search.trim().toLowerCase();
      return String(r.m.name||'').toLowerCase().includes(q) || String(r.m.category||'').toLowerCase().includes(q);
    })
    .sort((a,b)=>{
      const sev = r => !r.hasRecipe ? 0 : (r.hasRecipe && !r.hasPriceStore) ? 1 : (r.gpPct!=null && r.gpPct < targetGP - 0.1) ? 2 : 3;
      return sev(a)-sev(b) || String(a.m.category||'').localeCompare(String(b.m.category||''));
    });

  // ความครบถ้วนรายหมวด
  const byCat = {};
  scoped.forEach(r=>{
    const c = r.m.category || 'ไม่ระบุหมวด';
    if(!byCat[c]) byCat[c] = { cat:c, count:0, complete:0 };
    byCat[c].count++;
    if(r.complete) byCat[c].complete++;
  });
  const catRows = Object.values(byCat)
    .map(c=>({...c, pct: c.count>0 ? c.complete/c.count : 0}))
    .sort((a,b)=>a.pct-b.pct);

  const exportCSV = () => {
    const header = ['เมนู','หมวด','สถานะ','มีสูตร','มีต้นทุน','ตั้งราคา','ต้นทุน','ราคาหน้าร้าน','GP%','ขาดอะไร'];
    const rows = all.map(r=>[
      r.m.name||'', r.m.category||'', r.m.status||'',
      r.hasRecipe?'มี':'ไม่มี', r.hasCost?'มี':'ไม่มี', r.hasPriceStore?'มี':'ไม่มี',
      r.hasCost?r.e.total.toFixed(2):'', r.hasPriceStore?(+r.m.priceStore).toFixed(2):'',
      r.gpPct!=null?(r.gpPct*100).toFixed(1)+'%':'',
      r.gaps.join(' / ') || (r.gpPct!=null && r.gpPct<targetGP-0.1 ? 'GP ต่ำ' : 'ครบ'),
    ]);
    const csv = '﻿'+[header,...rows].map(r=>r.map(v=>`"${String(v??'').replace(/"/g,'""')}"`).join(',')).join('\n');
    const a=document.createElement('a');
    a.href=URL.createObjectURL(new Blob([csv],{type:'text/csv;charset=utf-8'}));
    a.download=`recipe-coverage-${new Date().toISOString().slice(0,10)}.csv`; a.click();
  };

  if(!total) return (
    <Empty icon="cup" title="ยังไม่มีเมนู" sub="เพิ่มเมนูก่อน แล้วกลับมาดูความครบถ้วนของสูตรและต้นทุน"
      action={<Button icon="plus" onClick={()=>go('menu')}>ไปหน้าเมนู</Button>}/>
  );

  const covColor = coverage>=0.9 ? 'var(--green)' : coverage>=0.6 ? 'var(--orange)' : 'var(--red)';
  const sevBadge = r => {
    if(!r.hasRecipe) return {tone:'red', label:'ยังไม่มีสูตร'};
    if(r.hasRecipe && !r.hasPriceStore) return {tone:'orange', label:'ยังไม่ตั้งราคา'};
    if(!r.hasCost) return {tone:'orange', label:'คิดต้นทุนไม่ได้'};
    return {tone:'gray', label:'GP ต่ำ'};
  };

  return (
    <div className="view-enter" style={{display:'grid',gap:18}}>
      {/* Controls */}
      <div className="no-print" style={{display:'flex',gap:10,flexWrap:'wrap',alignItems:'center'}}>
        <Segmented value={scope} onChange={setScope} options={[
          {value:'selling',label:'กำลังขาย'},{value:'all',label:'ทั้งหมด'},
        ]}/>
        <div style={{flex:1}}/>
        {noRecipe > 0 && <Button icon={batchBusy ? 'spin' : 'sparkle'} onClick={batchDraft} disabled={batchBusy}
          style={{background:'linear-gradient(135deg,#6366f1,#8b5cf6)',color:'#fff',border:'none',fontSize:13}}>
          สร้างสูตรร่างอัตโนมัติ ({noRecipe})
        </Button>}
        {priceable > 0 && <Button icon="wallet" onClick={bulkAutoPrice}
          style={{background:'var(--green)',color:'#fff',border:'none',fontSize:13}}>
          ตั้งราคาแนะนำ ({priceable})
        </Button>}
        <Button variant="secondary" icon="download" onClick={exportCSV}>CSV</Button>
      </div>

      {/* Stat cards */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:14}} className="r-2col">
        <Stat label="ความครบถ้วน" value={fmtPct(coverage,0)} icon="target" tone={covColor}
          sub={`${fmt(completeCount)}/${fmt(total)} เมนูมีสูตร+ราคาครบ`}/>
        <Stat label="ยังไม่มีสูตร" value={fmt(noRecipe)} icon="cup" tone={noRecipe>0?'var(--red)':'var(--green)'}
          sub={noRecipe>0?'ต้องเพิ่มสูตรก่อนคิดต้นทุน':'ทุกเมนูมีสูตรแล้ว'}/>
        <Stat label="มีสูตรแต่ยังไม่ตั้งราคา" value={fmt(noPrice)} icon="wallet" tone={noPrice>0?'var(--orange)':'var(--green)'}
          sub={noPrice>0?'ตั้งราคาเพื่อคำนวณ GP':'ตั้งราคาครบ'}/>
        <Stat label={`GP ต่ำกว่าเป้า (${fmtPct(targetGP,0)})`} value={fmt(lowGP)} icon="trend" tone={lowGP>0?'var(--red)':'var(--green)'}
          sub={lowGP>0?'ควรทบทวนราคา/ต้นทุน':'GP ผ่านเกณฑ์ทั้งหมด'}/>
      </div>

      {/* Coverage bar */}
      <Card>
        <SectionTitle sub="สัดส่วนเมนูที่มีข้อมูลครบ (สูตร → ต้นทุน → ราคา → GP)">ภาพรวมความครบถ้วน</SectionTitle>
        <div style={{height:14,background:'var(--chip)',borderRadius:7,overflow:'hidden',marginBottom:8}}>
          <div style={{height:'100%',width:`${Math.round(coverage*100)}%`,background:covColor,borderRadius:7,transition:'width .6s'}}/>
        </div>
        <div style={{display:'flex',justifyContent:'space-between',fontSize:12.5,color:'var(--ink-2)'}}>
          <span>ครบแล้ว {fmt(completeCount)} เมนู</span>
          <span>ยังขาด {fmt(total-completeCount)} เมนู</span>
        </div>
      </Card>

      {/* Per-category coverage */}
      {catRows.length>1 && <Card>
        <SectionTitle sub="หมวดที่ครบน้อยสุดอยู่บนสุด — โฟกัสปิดช่องว่างทีละหมวด">ความครบถ้วนรายหมวด</SectionTitle>
        <div style={{display:'grid',gap:9}}>
          {catRows.map(c=>(
            <div key={c.cat}>
              <div style={{display:'flex',justifyContent:'space-between',fontSize:12.5,marginBottom:3}}>
                <span style={{fontWeight:600}}>{c.cat}</span>
                <span style={{color:c.pct>=0.9?'var(--green)':c.pct>=0.6?'var(--orange)':'var(--red)',fontWeight:700}}>
                  {fmtPct(c.pct,0)} <span style={{fontWeight:400,color:'var(--ink-3)'}}>({c.complete}/{c.count})</span>
                </span>
              </div>
              <div style={{height:6,background:'var(--line-2)',borderRadius:4,overflow:'hidden'}}>
                <div style={{height:'100%',width:`${Math.round(c.pct*100)}%`,
                  background:c.pct>=0.9?'var(--green)':c.pct>=0.6?'var(--orange)':'var(--red)',borderRadius:4}}/>
              </div>
            </div>
          ))}
        </div>
      </Card>}

      {/* Gap checklist */}
      <Card>
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',gap:12,marginBottom:14,flexWrap:'wrap'}}>
          <SectionTitle sub="คลิกเมนูเพื่อไปเพิ่มสูตร/ตั้งราคา">รายการที่ต้องปิดช่องว่าง ({fmt(gapList.length)})</SectionTitle>
          <div style={{width:220}}><Search value={search} onChange={setSearch} placeholder="ค้นหาเมนู/หมวด"/></div>
        </div>
        {gapList.length===0
          ? <div style={{padding:'24px 0',textAlign:'center',color:'var(--green)',fontWeight:600}}>🎉 เยี่ยม! เมนู{scope==='selling'?'ที่กำลังขาย':'ทั้งหมด'}มีข้อมูลครบทุกเมนูแล้ว</div>
          : <div style={{overflowX:'auto'}}>
            <table style={{width:'100%',borderCollapse:'collapse',fontSize:13}}>
              <thead><tr style={{borderBottom:'1.5px solid var(--line)',color:'var(--ink-2)',fontSize:12}}>
                <th style={{textAlign:'left',padding:'8px 8px',fontWeight:600}}>เมนู</th>
                <th style={{textAlign:'left',padding:'8px 8px',fontWeight:600}}>หมวด</th>
                <th style={{textAlign:'center',padding:'8px 8px',fontWeight:600}}>สถานะ</th>
                <th style={{textAlign:'right',padding:'8px 8px',fontWeight:600}}>ต้นทุน</th>
                <th style={{textAlign:'right',padding:'8px 8px',fontWeight:600}}>ราคา</th>
                <th style={{textAlign:'right',padding:'8px 8px',fontWeight:600}}>GP%</th>
                <th style={{padding:'8px 8px',fontWeight:600}}></th>
              </tr></thead>
              <tbody>{gapList.map((r,i)=>{
                const b = sevBadge(r);
                return <tr key={r.m.id||i} style={{borderBottom:'1px solid var(--line-2)',background:i%2===1?'var(--surface-2)':'transparent'}}>
                  <td style={{padding:'9px 8px',fontWeight:600,cursor:'pointer'}} onClick={()=>go('menu')}>{r.m.name||'(ไม่มีชื่อ)'}</td>
                  <td style={{padding:'9px 8px',color:'var(--ink-2)',cursor:'pointer'}} onClick={()=>go('menu')}>{r.m.category||'–'}</td>
                  <td style={{padding:'9px 8px',textAlign:'center',cursor:'pointer'}} onClick={()=>go('menu')}><Badge tone={b.tone}>{b.label}</Badge></td>
                  <td className="tnum" style={{padding:'9px 8px',textAlign:'right',color:r.hasCost?'var(--ink)':'var(--ink-3)',cursor:'pointer'}} onClick={()=>go('menu')}>{r.hasCost?fmtB(r.e.total,2):'–'}</td>
                  <td className="tnum" style={{padding:'9px 8px',textAlign:'right',color:r.hasPriceStore?'var(--ink)':'var(--ink-3)',cursor:'pointer'}} onClick={()=>go('menu')}>{r.hasPriceStore?fmtB(r.m.priceStore):'–'}</td>
                  <td className="tnum" style={{padding:'9px 8px',textAlign:'right',fontWeight:700,cursor:'pointer',
                    color:r.gpPct==null?'var(--ink-3)':r.gpPct>=targetGP?'var(--green)':r.gpPct>=targetGP-0.1?'var(--orange)':'var(--red)'}} onClick={()=>go('menu')}>
                    {r.gpPct!=null?fmtPct(r.gpPct,0):'–'}
                  </td>
                  <td style={{padding:'9px 4px',textAlign:'center',whiteSpace:'nowrap'}}>
                    {!r.hasRecipe &&
                      <button onClick={e=>{e.stopPropagation();draftOne(r.m);}}
                        title="สร้างสูตรร่างอัตโนมัติ"
                        style={{padding:'4px 10px',borderRadius:7,fontSize:12,fontWeight:700,cursor:'pointer',border:'none',
                          background:'linear-gradient(135deg,#6366f1,#8b5cf6)',color:'#fff',whiteSpace:'nowrap'}}>
                        ✨ สร้าง
                      </button>}
                    {r.hasRecipe && r.hasCost && !r.hasPriceStore &&
                      <button onClick={e=>{e.stopPropagation();priceOne(r.m,r.e);}}
                        title={`ตั้งราคาแนะนำ ฿${Math.ceil(r.e.total/(1-targetGP)/5)*5}`}
                        style={{padding:'4px 10px',borderRadius:7,fontSize:12,fontWeight:700,cursor:'pointer',border:'none',
                          background:'var(--green)',color:'#fff',whiteSpace:'nowrap'}}>
                        ฿ ตั้งราคา
                      </button>}
                  </td>
                </tr>;
              })}</tbody>
            </table>
          </div>}
      </Card>

      <p style={{fontSize:11.5,color:'var(--ink-3)',lineHeight:1.7}}>
        นิยาม "ครบ" = มีสูตร (วัตถุดิบ/แพ็กเกจ/สูตรฐาน) → คิดต้นทุนได้ → ตั้งราคาหน้าร้าน → คำนวณ GP% ได้ ·
        เกณฑ์ GP เป้าหมาย {fmtPct(targetGP,0)} (ปรับได้ที่ตั้งค่า) · ระบบ JEBAR Operate
      </p>
    </div>
  );
}

Object.assign(window, { RecipeCoveragePage, coverageRows });
