/* ============ ForecastTab — terminal reskin of ForecastCalc ============
   Source: profit-calc-clean-source.html lines 2396-2732. Math identical. */

function ForecastTab({products,distroState}){
  const distroModelShared=distroState.distroModelShared;
  const distroMarginShared=distroState.distroMarginShared;
  const distroPricingModeShared=distroState.distroPricingModeShared;
  const salesPctShared=distroState.salesPctShared;
  const sampleRateShared=distroState.sampleRateShared;
  const testingAnnualShared=distroState.testingAnnualShared||24000;

  const [numStores,setNumStores]=useState(50);
  const [avgOrder,setAvgOrder]=useState(500);
  const [avgOrderOverride,setAvgOrderOverride]=useState(false);
  const [ordersPerMonth,setOrdersPerMonth]=useState(2);
  const [growthPct,setGrowthPct]=useState(5);
  const [distroMargin,setDistroMargin]=useState(distroMarginShared);
  const [distroOverride,setDistroOverride]=useState(false);
  const [salesPct,setSalesPct]=useState(salesPctShared);
  const [salesOverride,setSalesOverride]=useState(false);
  const [testingAnnual,setTestingAnnual]=useState(testingAnnualShared);
  const [testingOverride,setTestingOverride]=useState(false);
  const [sampleRate,setSampleRate]=useState(sampleRateShared);
  const [sampleOverride,setSampleOverride]=useState(false);
  const [months,setMonths]=useState(12);
  const [chartView,setChartView]=useState('revenue');
  const [overhead,setOverhead]=useState(1000);
  const [rent,setRent]=useState(4000);
  const [payroll,setPayroll]=useState(4000);

  const totalUnits=products.reduce((s,p)=>s+p.units,0);
  const totalWsRev=products.reduce((s,p)=>s+p.wsList*p.units,0);
  const totalCOGS=products.reduce((s,p)=>s+p.totalCOGS*p.units,0);
  const derivedAvgOrder=totalUnits>0?Math.round(totalWsRev/Math.max(totalUnits,1)*10):500;

  useEffect(()=>{if(!distroOverride)setDistroMargin(distroMarginShared);},[distroMarginShared]);
  useEffect(()=>{if(!salesOverride)setSalesPct(salesPctShared);},[salesPctShared]);
  useEffect(()=>{if(!sampleOverride)setSampleRate(sampleRateShared);},[sampleRateShared]);
  useEffect(()=>{if(!testingOverride)setTestingAnnual(testingAnnualShared);},[testingAnnualShared]);
  useEffect(()=>{if(!avgOrderOverride&&derivedAvgOrder>0)setAvgOrder(derivedAvgOrder);},[derivedAvgOrder]);

  const safeDistroMargin=pct(distroMargin);
  const safeSalesPct=pct(salesPct);
  const safeSampleRate=pct(sampleRate);
  const safeTestingAnnual=nonNegative(testingAnnual);
  const safeMonths=Math.max(1,Math.floor(nonNegative(months)||1));
  const monthlyGross=nonNegative(numStores)*nonNegative(avgOrder)*nonNegative(ordersPerMonth);
  const blendedCOGSPct=totalWsRev>0?totalCOGS/totalWsRev:0.40;
  const fixedMonthly=nonNegative(overhead)+nonNegative(rent)+nonNegative(payroll);
  const isWholesaleModel=distroModelShared==='wholesale';
  const isFlatMode=isWholesaleModel&&distroPricingModeShared==='flat';
  const distroRate=isFlatMode?0:safeDistroMargin/100;
  const effectiveRevenueRate=isWholesaleModel&&!isFlatMode?1-distroRate:1;

  const forecast=useMemo(()=>{
    const fg=[];let cr=0,cp=0;
    for(let m=1;m<=safeMonths;m++){
      const g=Math.pow(Math.max(0,1+(growthPct/100)),m-1);
      const rev=monthlyGross*g;
      const cogs=rev*blendedCOGSPct;
      const distro=rev*distroRate;
      const effectiveRev=isWholesaleModel&&!isFlatMode?rev-distro:rev;
      const sales=effectiveRev*(safeSalesPct/100);
      const testing=safeTestingAnnual/12;
      const samples=effectiveRev*(safeSampleRate/100)*blendedCOGSPct;
      const np=rev-cogs-distro-sales-testing-samples-fixedMonthly;
      cr+=rev;cp+=np;
      fg.push({month:m,rev,cogs,distro,sales,testing,samples,fixed:fixedMonthly,netProfit:np,cumRev:cr,cumProfit:cp});
    }
    return fg;
  },[safeMonths,growthPct,monthlyGross,blendedCOGSPct,distroRate,safeSalesPct,safeTestingAnnual,safeSampleRate,fixedMonthly,isWholesaleModel,isFlatMode]);

  const cumRev=forecast.reduce((s,f)=>s+f.rev,0);
  const cumProfit=forecast.length?forecast[forecast.length-1].cumProfit:0;
  const maxRev=forecast.length?Math.max(...forecast.map(f=>f.rev)):0;
  const maxProfit=forecast.length?Math.max(...forecast.map(f=>Math.abs(f.netProfit))):0;
  const maxCum=forecast.length?Math.max(...forecast.map(f=>Math.abs(f.cumProfit))):0;
  const breakEvenMonth=forecast.findIndex(f=>f.cumProfit>0);
  const finalRev=forecast.length?forecast[forecast.length-1].rev:0;

  /* break-even analysis */
  const varCostPct=blendedCOGSPct+distroRate+(effectiveRevenueRate*(safeSalesPct/100))+(effectiveRevenueRate*(safeSampleRate/100)*blendedCOGSPct);
  const contrib=1-Math.min(varCostPct,0.99);
  const revToCoverFixed=fixedMonthly/contrib;
  const storesToBreakEven=Math.ceil(revToCoverFixed/(nonNegative(avgOrder)*nonNegative(ordersPerMonth)||1));

  return(<div className="calc-page">
    <div className="readme">
      <p><strong style={{color:'var(--text)'}}>12-month projection.</strong> revenue = <code>stores × avg_order × orders/month</code>, compounded at your monthly growth rate. cogs is blended from your product mix ({totalUnits>0?`${totalUnits.toLocaleString()} units, ${(blendedCOGSPct*100).toFixed(0)}% cogs`:'add products for accurate margins'}). fixed costs (rent, payroll, oh) deducted monthly.</p>
      <p>fields marked <span className="synced">[SYNCED]</span> auto-populate from the distro tab — edit to override, click again to re-sync.</p>
    </div>

    <Section idx={1} title="baseline assumptions" active>
      <p className="section-desc">sizing the business. how many stores × average order × cadence. growth rate compounds monthly.</p>
      <div className="g4">
        <Field highlight label="num_stores" value={numStores} onChange={setNumStores}/>
        <SyncedField label="avg_ws_order" prefix="$" value={avgOrder} onChange={setAvgOrder} synced={!avgOrderOverride&&totalUnits>0} onOverride={()=>setAvgOrderOverride(true)} reSync={()=>{setAvgOrderOverride(false);if(derivedAvgOrder>0)setAvgOrder(derivedAvgOrder);}} hint="per store · derived from mix"/>
        <Field label="orders_per_month" value={ordersPerMonth} onChange={setOrdersPerMonth}/>
        <Field label="monthly_growth" value={growthPct} onChange={setGrowthPct} suffix="%"/>
      </div>
    </Section>

    <Section idx={2} title="deduction inputs" active>
      <p className="section-desc">these all sync from the distro tab. override any field to model a custom scenario without touching the rest of the app.</p>
      <div className="g4">
        <SyncedField label="distro_margin" value={distroMargin} onChange={setDistroMargin} suffix="%" synced={!distroOverride} onOverride={()=>setDistroOverride(true)} reSync={()=>{setDistroOverride(false);setDistroMargin(distroMarginShared);}}/>
        <SyncedField label="sales_commission" value={salesPct} onChange={setSalesPct} suffix="%" synced={!salesOverride} onOverride={()=>setSalesOverride(true)} reSync={()=>{setSalesOverride(false);setSalesPct(salesPctShared);}}/>
        <SyncedField label="annual_testing" prefix="$" value={testingAnnual} onChange={setTestingAnnual} synced={!testingOverride} onOverride={()=>setTestingOverride(true)} reSync={()=>{setTestingOverride(false);setTestingAnnual(testingAnnualShared);}}/>
        <SyncedField label="sample_rate" value={sampleRate} onChange={setSampleRate} suffix="%" synced={!sampleOverride} onOverride={()=>setSampleOverride(true)} reSync={()=>{setSampleOverride(false);setSampleRate(sampleRateShared);}}/>
      </div>
      <div className="sub-head" style={{marginTop:14}}><span className="mark">//</span><span className="title">fixed_costs</span><span className="note">— monthly, deducted flat</span></div>
      <div className="g4">
        <Field label="monthly_overhead" prefix="$" value={overhead} onChange={setOverhead}/>
        <Field label="monthly_rent" prefix="$" value={rent} onChange={setRent}/>
        <Field label="monthly_payroll" prefix="$" value={payroll} onChange={setPayroll}/>
        <Field label="forecast_period" value={months} onChange={setMonths} suffix=" mo"/>
      </div>
    </Section>

    <Section idx={3} title="headline numbers" active>
      <div className="g4">
        <Stat label="monthly_gross  (start)" value={fmtK(monthlyGross)} sub={`${nonNegative(numStores)} × ${fmt(nonNegative(avgOrder))} × ${nonNegative(ordersPerMonth)}/mo`}/>
        <Stat label={`month_${safeMonths}_revenue`} value={fmtK(finalRev)} sub={`${growthPct}% monthly growth`} tone="pos"/>
        <Stat label={`${safeMonths}mo_total_rev`} value={fmtK(cumRev)} sub="wholesale invoiced"/>
        <Stat label={`${safeMonths}mo_net_profit`} value={fmtK(cumProfit)} sub={`${cumRev>0?(cumProfit/cumRev*100).toFixed(1):0}% net margin`} tone={cumProfit>0?'pos':'neg'}/>
      </div>
      {breakEvenMonth>=0&&<div className="breakeven-banner">
        <span className="be-label">[ breakeven ]</span>
        <span className="be-month">month_{String(breakEvenMonth+1).padStart(2,'0')}</span>
        <span className="be-note">cumulative profit turns positive after {breakEvenMonth+1} month{breakEvenMonth>0?'s':''}</span>
      </div>}
      {breakEvenMonth<0&&<div className="breakeven-banner warn">
        <span className="be-label">[ no_breakeven ]</span>
        <span className="be-note">never turns profitable over the {safeMonths}-month window. review fixed costs, growth rate, or order size.</span>
      </div>}
    </Section>

    <Section idx={4} title="blended margin analysis" active>
      <p className="section-desc">the averaged economics across your product mix, weighted by unit volume.</p>
      <div className="g4">
        <Stat label="blended_cogs_pct" value={`${(blendedCOGSPct*100).toFixed(1)}%`} sub="% of ws revenue"/>
        <Stat label="blended_gross_margin" value={`${((1-blendedCOGSPct)*100).toFixed(1)}%`} tone={(1-blendedCOGSPct)>=0.5?'pos':(1-blendedCOGSPct)>=0.3?'warn':'neg'}/>
        <Stat label="effective_net_margin" value={`${(cumRev>0?(cumProfit/cumRev)*100:0).toFixed(1)}%`} sub="after all costs"/>
        <Stat label="annual_run_rate" value={fmtK(finalRev*12)} sub="final month × 12"/>
      </div>
      <div className="g3" style={{marginTop:12}}>
        <Stat label="monthly_fixed" value={fmtK(fixedMonthly)} sub={`rent ${fmtK(rent)} + payroll ${fmtK(payroll)} + oh ${fmtK(overhead)}`} tone="neg"/>
        <Stat label="rev_to_cover_fixed" value={fmtK(revToCoverFixed)} sub={`after cogs ${(blendedCOGSPct*100).toFixed(0)}% + distro ${(distroRate*100).toFixed(0)}% + sales ${safeSalesPct}%`} tone="warn"/>
        <Stat label="stores_to_breakeven" value={String(storesToBreakEven)} sub={`at ${fmt(nonNegative(avgOrder))} × ${nonNegative(ordersPerMonth)}/mo per store`}/>
      </div>
    </Section>

    <Section idx={5} title="visual forecast" active>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12,gap:12,flexWrap:'wrap'}}>
        <p className="section-desc" style={{margin:0,flex:1,minWidth:260}}>month-over-month projection. toggle to see revenue, net profit, cumulative, or the cost breakdown stack.</p>
        <Seg options={[
          {value:'revenue',label:'revenue'},
          {value:'profit',label:'net_profit'},
          {value:'cumulative',label:'cumulative'},
          {value:'costs',label:'cost_stack'}
        ]} value={chartView} onChange={setChartView}/>
      </div>
      <div className="forecast-chart">
        {forecast.map(f=>{
          const isNeg=f.netProfit<0;
          let bars=[];
          if(chartView==='revenue'){
            bars=[{val:f.rev,label:fmtK(f.rev),cls:'pos',pct:maxRev>0?(f.rev/maxRev)*100:0}];
          }else if(chartView==='profit'){
            bars=[{val:f.netProfit,label:fmtK(f.netProfit),cls:isNeg?'neg':'pos',pct:maxProfit>0?(Math.abs(f.netProfit)/maxProfit)*100:0,flip:isNeg}];
          }else if(chartView==='cumulative'){
            bars=[{val:f.cumProfit,label:fmtK(f.cumProfit),cls:f.cumProfit<0?'neg':'pos',pct:maxCum>0?(Math.abs(f.cumProfit)/maxCum)*100:0,flip:f.cumProfit<0}];
          }else{
            /* cost stack — parts summing to revenue */
            const parts=[
              {val:f.cogs,cls:'cogs'},
              {val:f.distro,cls:'distro'},
              {val:f.sales,cls:'sales'},
              {val:f.samples+f.testing,cls:'samples'},
              {val:f.fixed,cls:'fixed'},
              {val:Math.max(0,f.netProfit),cls:'net'}
            ];
            bars=parts.map(p=>({val:p.val,label:'',cls:'stack-'+p.cls,pct:maxRev>0?(p.val/maxRev)*100:0,stack:true}));
          }
          return(<div key={f.month} className="chart-col">
            <div className="chart-value">{chartView==='costs'?fmtK(f.rev):bars[0].label}</div>
            <div className="chart-bar-outer">
              {bars.map((b,i)=>(
                <div key={i} className={`chart-bar ${b.cls} ${b.flip?'flipped':''}`} style={{height:`${b.pct}%`}}></div>
              ))}
            </div>
            <div className="chart-label">m{String(f.month).padStart(2,'0')}</div>
          </div>);
        })}
      </div>
      {chartView==='costs'&&<div className="legend">
        <span><span className="dot stack-cogs"></span>cogs</span>
        <span><span className="dot stack-distro"></span>distro</span>
        <span><span className="dot stack-sales"></span>sales</span>
        <span><span className="dot stack-samples"></span>samples+testing</span>
        <span><span className="dot stack-fixed"></span>fixed</span>
        <span><span className="dot stack-net"></span>net_profit</span>
      </div>}
    </Section>

    <Section idx={6} title="monthly detail" active>
      <p className="section-desc">the raw numbers, month by month. every deduction, cumulative profit, and breakeven point.</p>
      <div className="sku-table">
        <table>
          <thead><tr>
            <th>month</th><th>rev</th><th>cogs</th><th>distro</th><th>sales</th><th>testing</th><th>samples</th><th>fixed</th><th>net</th><th>cum_profit</th>
          </tr></thead>
          <tbody>
            {forecast.map(f=>(<tr key={f.month} className={f.cumProfit>0?'breakeven-row':''}>
              <td className="mono">m{String(f.month).padStart(2,'0')}</td>
              <td className="pos">{fmtK(f.rev)}</td>
              <td className="neg">−{fmtK(f.cogs)}</td>
              <td className="warn">−{fmtK(f.distro)}</td>
              <td className="warn">−{fmtK(f.sales)}</td>
              <td className="warn">−{fmtK(f.testing)}</td>
              <td className="warn">−{fmtK(f.samples)}</td>
              <td className="neg">−{fmtK(f.fixed)}</td>
              <td className={f.netProfit>0?'pos bold':'neg bold'}>{fmtK(f.netProfit)}</td>
              <td className={f.cumProfit>0?'pos bold':'neg bold'}>{fmtK(f.cumProfit)}</td>
            </tr>))}
          </tbody>
        </table>
      </div>
    </Section>
  </div>);
}

/* SYNCED field helper — shows [SYNCED] tag, [CUSTOM] click-to-resync. Mirrors Field styling. */
function SyncedField({label,value,onChange,prefix,suffix,synced,onOverride,reSync,hint}){
  const [editing,setEditing]=useState(false);
  const [draft,setDraft]=useState('');
  return(<label className={`fld key`}>
    <div className="fld-label" style={{justifyContent:'space-between',width:'100%',display:'flex'}}>
      <span>{label}</span>
      {synced?<span className="synced" title="auto-populating from distro tab">[SYNCED]</span>
        :<span className="custom" onClick={(e)=>{e.preventDefault();reSync();}} title="click to re-sync">[CUSTOM ↺]</span>}
    </div>
    <div className="fld-input mono">
      {prefix&&<span className="prefix">{prefix}</span>}
      <input type="text" inputMode="decimal" value={editing?draft:value}
        onFocus={()=>{setEditing(true);setDraft(String(value));}}
        onChange={e=>{const v=e.target.value;setDraft(v);const n=parseFloat(v);if(!isNaN(n)){onChange(n);if(onOverride)onOverride();}}}
        onBlur={()=>{setEditing(false);const n=parseFloat(draft);onChange(isNaN(n)?0:n);}}/>
      {suffix&&<span className="suffix">{suffix}</span>}
    </div>
    {hint&&<div className="fld-hint">{hint}</div>}
  </label>);
}

Object.assign(window,{ForecastTab,SyncedField});
