// app/uwsections.jsx — Quick & Full underwriting tabs.
// Quick UW = pricing + going-in / stabilized cap. Full UW = income & economic vacancy
// (current vs stabilized), operating assumptions, financing, refinance, and the
// multi-year cash-flow model. Loaded after components.jsx + dealDetail.jsx.
const { useState: useSU } = React;
const {
  Card, Seg, Icon, FieldInput, SectionHead, CalcRow, PerUnit, BannerShell, FoundRow, MissingRow,
  fmtMoney, fmtShort, fmtPct, fmtNum, computeUW, computeMetrics,
} = window;

const moneyFull = (v) => (v == null || isNaN(v)) ? '—' : (v < 0 ? '−' : '') + '$' + Math.round(Math.abs(v)).toLocaleString('en-US');
const pct1 = (v) => (v == null || isNaN(v)) ? '—' : (v * 100).toFixed(1) + '%';
const round1 = (v) => Math.round(v * 1000) / 10;
const num = (v) => Number(v) || 0;

function dateBox(value, onChange) {
  return (
    <input type="date" value={value || ''} onChange={(e) => onChange(e.target.value || null)}
      style={{ border: '1px solid var(--line-2)', borderRadius: 6, padding: '0 8px', background: 'var(--panel)',
        fontSize: 12.5, height: 32, width: '100%', boxSizing: 'border-box', color: 'var(--ink)', fontFamily: 'var(--font)' }}
      onFocus={(e) => { e.target.style.borderColor = 'var(--accent)'; e.target.style.boxShadow = '0 0 0 3px var(--accent-soft)'; }}
      onBlur={(e) => { e.target.style.borderColor = 'var(--line-2)'; e.target.style.boxShadow = 'none'; }} />
  );
}

/* compact assumption field (label + small input, fixed width) */
function CAssump({ label, hint, w = 124, children }) {
  return (
    <div style={{ width: w }}>
      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 600, letterSpacing: '.03em', textTransform: 'uppercase', marginBottom: 4 }}>{label}</div>
      {children}
      {hint && <div style={{ fontSize: 10, color: 'var(--faint)', marginTop: 3, lineHeight: 1.3 }}>{hint}</div>}
    </div>
  );
}
function CompactGrid({ children }) {
  return <div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px 18px', marginTop: 14 }}>{children}</div>;
}

/* ───────────── Pricing & Basis (shown on BOTH tabs) ───────────── */
function PricingBasis({ deal, set, m }) {
  const ask = num(deal.askPrice), uw = num(deal.purchasePrice);
  const offGuidance = ask > 0 && uw > 0 ? (uw - ask) / ask : null; // negative = below ask
  const dollarDelta = ask > 0 && uw > 0 ? ask - uw : null;          // positive = below ask
  const basis = uw + num(deal.capex);
  return (
    <Card>
      <SectionHead icon="bank" title="Pricing & Basis" desc="Acquisition pricing — feeds the cap-rate math and the cash-flow model." />
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: '16px 22px', marginTop: 16 }}>
        <div><Lbl>Ask Price</Lbl><FieldInput value={deal.askPrice} onChange={(v) => set('askPrice', v || 0)} prefix="$" /><PerUnit total={deal.askPrice} units={m.units} /></div>
        <div><Lbl>UW Price</Lbl><FieldInput value={deal.purchasePrice} onChange={(v) => set('purchasePrice', v || 0)} prefix="$" /><PerUnit total={deal.purchasePrice} units={m.units} /></div>
        <div><Lbl>CapEx Budget</Lbl><FieldInput value={deal.capex} onChange={(v) => set('capex', v || 0)} prefix="$" /><PerUnit total={deal.capex} units={m.units} /></div>
      </div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--line)' }}>
        <GuidancePill label="UW vs. Guidance" value={offGuidance == null ? '—'
          : (offGuidance <= 0 ? (Math.abs(offGuidance) * 100).toFixed(1) + '% below ask' : '+' + (offGuidance * 100).toFixed(1) + '% over ask')}
          sub={dollarDelta == null ? '' : (dollarDelta >= 0 ? moneyFull(dollarDelta) + ' below ask' : moneyFull(Math.abs(dollarDelta)) + ' over ask')}
          accent={offGuidance == null ? 'var(--faint)' : offGuidance <= 0 ? 'var(--pos)' : 'var(--neg)'} />
        <GuidancePill label="Total Basis" value={basis ? moneyFull(basis) : '—'} sub={m.units ? moneyFull(basis / m.units) + ' / unit' : ''} />
      </div>
    </Card>
  );
}
function GuidancePill({ label, value, sub, accent }) {
  return (
    <div style={{ flex: '1 1 200px', background: 'var(--panel-2)', border: '1px solid var(--line)', borderRadius: 8, padding: '9px 13px' }}>
      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', marginBottom: 3 }}>{label}</div>
      <div className="num" style={{ fontSize: 15, fontWeight: 700, color: accent || 'var(--ink)' }}>{value}</div>
      {sub && <div className="num" style={{ fontSize: 11, color: 'var(--faint)', marginTop: 1 }}>{sub}</div>}
    </div>
  );
}
function Lbl({ children }) {
  return <div style={{ fontSize: 10.5, color: 'var(--muted)', fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', marginBottom: 5 }}>{children}</div>;
}

/* ───────────── Income & Economic Vacancy (Full tab) ───────────── */
// A small inline note shown to the right of an input
function Note({ children }) {
  return <div className="num" style={{ fontSize: 11, color: 'var(--faint)', marginTop: 3 }}>{children}</div>;
}
// One vacancy line with paired % / $ inputs (editing either updates the stored $)
function VacLine({ label, value, gpr, onChange }) {
  const pct = gpr > 0 ? (value / gpr) * 100 : 0;
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 84px 116px', gap: 8, alignItems: 'center', padding: '6px 0' }}>
      <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>{label}</span>
      <FieldInput value={Math.round(pct * 10) / 10} suffix="%" align="left" onChange={(v) => onChange(gpr > 0 ? Math.round((num(v)) / 100 * gpr) : 0)} />
      <FieldInput value={value} prefix="$" onChange={(v) => onChange(num(v))} />
    </div>
  );
}
function OutRow({ label, value, strong, accent, hint }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 10,
      padding: '8px 0', borderTop: '1px solid var(--line)' }}>
      <span style={{ fontSize: strong ? 13 : 12.5, color: 'var(--ink)', fontWeight: strong ? 600 : 400 }}>
        {label}{hint && <span style={{ fontSize: 11, color: 'var(--faint)', fontWeight: 400 }}> · {hint}</span>}
      </span>
      <span className="num" style={{ fontSize: strong ? 15 : 13, fontWeight: strong ? 700 : 500, color: accent || 'var(--ink)' }}>{value}</span>
    </div>
  );
}
function PanelHead({ children, accent }) {
  return (
    <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase',
      color: accent || 'var(--muted)', marginBottom: 6 }}>{children}</div>
  );
}

function IncomeVacancySection({ deal, set }) {
  const units = deal.units || 1;
  const gpr = num(deal.gprAnnual);
  const phys = num(deal.physVacLoss), ltl = num(deal.lossToLease);
  const comb = num(deal.concessions) + num(deal.badDebt);
  const other = num(deal.otherIncome);
  const totalLoss = phys + ltl + comb;
  const inPlaceVac = gpr > 0 ? totalLoss / gpr : 0;
  const inPlaceEGI = gpr > 0 ? gpr - totalLoss + other : num(deal.trailingEGI);
  const curOpex = num(deal.currentOpexTotal);
  const inPlaceNOI = inPlaceEGI - curOpex;

  const stabVac = (deal.stabEconVac == null || deal.stabEconVac === '') ? inPlaceVac : num(deal.stabEconVac) / 100;
  const stabOther = (deal.stabOtherIncome == null || deal.stabOtherIncome === '') ? other : num(deal.stabOtherIncome);
  const stabEGI = gpr * (1 - stabVac) + stabOther;
  const stabOpexPerUnit = num(deal.marketOpexPerUnit);
  const stabOpex = stabOpexPerUnit * units;
  const stabNOI = stabEGI - stabOpex;
  const rpu = gpr > 0 ? gpr / units / 12 : 0;
  const setComb = (v) => { set('concessions', v); set('badDebt', 0); };

  const panel = { background: 'var(--panel-2)', border: '1px solid var(--line)', borderRadius: 9, padding: '12px 14px' };

  return (
    <Card>
      <SectionHead icon="pulse" title="Income & Economic Vacancy"
        desc="Left = in-place (T-12 / rent roll). Right = our stabilized assumptions. Parse a Rent Roll & T-12 to auto-fill." />

      {/* GPR — applies to both columns */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 200px 200px', gap: 14, alignItems: 'end', marginTop: 16,
        paddingBottom: 14, borderBottom: '1px solid var(--line)' }}>
        <div>
          <Lbl>Gross Potential Rent</Lbl>
          <div style={{ fontSize: 11.5, color: 'var(--muted)' }}>Annual market rent across all units — the basis for every vacancy line below.</div>
        </div>
        <div>
          <FieldInput value={deal.gprAnnual} onChange={(v) => set('gprAnnual', v || 0)} prefix="$" />
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="num" style={{ fontSize: 17, fontWeight: 700, color: 'var(--ink)' }}>{rpu ? moneyFull(rpu) : '—'}</div>
          <div style={{ fontSize: 11, color: 'var(--faint)' }}>rent / unit / month</div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 16 }}>
        {/* CURRENT / T-12 */}
        <div style={panel}>
          <PanelHead>Current · T-12 / Rent Roll</PanelHead>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 84px 116px', gap: 8, padding: '0 0 2px' }}>
            <span />
            <span style={{ fontSize: 9.5, color: 'var(--faint)', fontWeight: 600, textTransform: 'uppercase', textAlign: 'center' }}>% of GPR</span>
            <span style={{ fontSize: 9.5, color: 'var(--faint)', fontWeight: 600, textTransform: 'uppercase', textAlign: 'center' }}>Annual $</span>
          </div>
          <VacLine label="Physical Vacancy" value={phys} gpr={gpr} onChange={(v) => set('physVacLoss', v)} />
          <VacLine label="Loss to Lease" value={ltl} gpr={gpr} onChange={(v) => set('lossToLease', v)} />
          <VacLine label="Concessions & Bad Debt" value={comb} gpr={gpr} onChange={setComb} />
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 116px', gap: 8, alignItems: 'center', padding: '6px 0' }}>
            <div>
              <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>Other Income</span>
              <Note>{other && units ? moneyFull(other / units / 12) + ' / unit / mo' : '—'}</Note>
            </div>
            <FieldInput value={deal.otherIncome} onChange={(v) => set('otherIncome', v || 0)} prefix="$" />
          </div>
          <OutRow label="In-Place Effective Gross Income" value={moneyFull(inPlaceEGI)} strong accent="var(--accent)"
            hint={pct1(inPlaceVac) + ' econ. vacancy'} />
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 116px', gap: 8, alignItems: 'center', padding: '8px 0 6px' }}>
            <div>
              <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>Current Operating Expenses</span>
              <Note>{curOpex && units ? moneyFull(curOpex / units) + ' / unit' : '—'}</Note>
            </div>
            <FieldInput value={deal.currentOpexTotal} onChange={(v) => set('currentOpexTotal', v || 0)} prefix="$" />
          </div>
          <OutRow label="In-Place NOI" value={moneyFull(inPlaceNOI)} strong />
        </div>

        {/* STABILIZED */}
        <div style={{ ...panel, borderColor: 'var(--accent-soft)' }}>
          <PanelHead accent="var(--accent-2)">Stabilized · Our Assumptions</PanelHead>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 116px', gap: 8, alignItems: 'center', padding: '6px 0' }}>
            <div>
              <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>Economic Vacancy</span>
              <Note>{gpr ? moneyFull(gpr * stabVac) + ' / yr' : '—'}</Note>
            </div>
            <FieldInput value={deal.stabEconVac} onChange={(v) => set('stabEconVac', v)} suffix="%" align="left" placeholder={String(round1(inPlaceVac))} />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 116px', gap: 8, alignItems: 'center', padding: '6px 0' }}>
            <div>
              <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>Other Income</span>
              <Note>{stabOther && units ? moneyFull(stabOther / units / 12) + ' / unit / mo · carries trailing' : 'carries trailing'}</Note>
            </div>
            <FieldInput value={deal.stabOtherIncome} onChange={(v) => set('stabOtherIncome', v)} prefix="$" placeholder={String(Math.round(other))} />
          </div>
          <OutRow label="Stabilized Effective Gross Income" value={moneyFull(stabEGI)} strong accent="var(--accent)" />
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 116px', gap: 8, alignItems: 'center', padding: '8px 0 6px' }}>
            <div>
              <span style={{ fontSize: 12.5, color: 'var(--ink)' }}>OpEx / Unit</span>
              <Note>{stabOpex ? moneyFull(stabOpex) + ' total' : '—'}</Note>
            </div>
            <FieldInput value={deal.marketOpexPerUnit} onChange={(v) => set('marketOpexPerUnit', v || 0)} prefix="$" />
          </div>
          <OutRow label="Stabilized NOI" value={moneyFull(stabNOI)} strong accent="var(--pos)" />
        </div>
      </div>
    </Card>
  );
}

/* ───────────── Operating Assumptions (compact) ───────────── */
function AssumptionsSection({ deal, set, uw }) {
  const hold = uw.hold;
  const vacOv = deal.vacOverride || {};
  const setOv = (y, v) => set('vacOverride', { ...vacOv, [y]: v });
  const clearOv = () => set('vacOverride', {});
  const hasOv = Object.keys(vacOv).length > 0;
  return (
    <Card>
      <SectionHead icon="calc" title="Operating Assumptions"
        desc="Growth, exit and costs. Stabilized vacancy is set in the income section above; this is the burn-off path to it." />
      <CompactGrid>
        <CAssump label="Hold Period" hint="years"><FieldInput value={deal.holdYears == null ? 10 : deal.holdYears} onChange={(v) => set('holdYears', v || 1)} suffix="yrs" align="left" /></CAssump>
        <CAssump label="GPR Growth"><FieldInput value={deal.gprGrowth == null ? 3 : deal.gprGrowth} onChange={(v) => set('gprGrowth', v)} suffix="%" align="left" /></CAssump>
        <CAssump label="OpEx Growth"><FieldInput value={deal.opexGrowth == null ? 2.5 : deal.opexGrowth} onChange={(v) => set('opexGrowth', v)} suffix="%" align="left" /></CAssump>
        <CAssump label="Exit Cap Rate" hint="sale = NOI ÷ cap"><FieldInput value={deal.exitCap == null ? 6 : deal.exitCap} onChange={(v) => set('exitCap', v)} suffix="%" align="left" /></CAssump>
        <CAssump label="Stabilization Yr" hint="reaches target by"><FieldInput value={deal.stabYear == null ? 3 : deal.stabYear} onChange={(v) => set('stabYear', v || 1)} suffix="yr" align="left" /></CAssump>
        <CAssump label="Acq. Closing Cost" hint="% of price"><FieldInput value={deal.closingPct == null ? 5 : deal.closingPct} onChange={(v) => set('closingPct', v)} suffix="%" align="left" /></CAssump>
        <CAssump label="Selling Costs" hint="% of sale"><FieldInput value={deal.sellingPct == null ? 4 : deal.sellingPct} onChange={(v) => set('sellingPct', v)} suffix="%" align="left" /></CAssump>
      </CompactGrid>

      {/* vacancy glide */}
      <div style={{ marginTop: 18, paddingTop: 14, borderTop: '1px solid var(--line)' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <div>
            <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink)' }}>Economic Vacancy Schedule</div>
            <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 1 }}>
              Auto step-down from {pct1(uw.inPlaceEconVac)} to {pct1(uw.stabVac)} by year {uw.stabYear}. Override any year.
            </div>
          </div>
          {hasOv && <button onClick={clearOv} style={{ border: '1px solid var(--line-2)', background: 'var(--panel-2)', color: 'var(--slate)', borderRadius: 6, padding: '4px 10px', fontSize: 11.5, fontWeight: 500, cursor: 'pointer' }}>Reset to auto</button>}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: `repeat(${hold}, 1fr)`, gap: 7 }}>
          {Array.from({ length: hold }, (_, i) => i + 1).map((y) => {
            const overridden = vacOv[y] != null && vacOv[y] !== '';
            const shown = overridden ? Number(vacOv[y]) : round1(uw.defaultVac(y));
            return (
              <div key={y} style={{ background: 'var(--panel-2)', border: '1px solid var(--line)', borderRadius: 7, padding: '7px 8px' }}>
                <div style={{ fontSize: 9.5, color: 'var(--muted)', fontWeight: 600, marginBottom: 4 }}>YR {y}</div>
                <div style={{ display: 'inline-flex', alignItems: 'center', border: `1px solid ${overridden ? 'var(--accent)' : 'var(--line-2)'}`, borderRadius: 6, background: 'var(--panel)', height: 28, width: '100%', overflow: 'hidden' }}>
                  <input className="num" value={shown} inputMode="decimal"
                    onChange={(e) => setOv(y, e.target.value.replace(/[^0-9.]/g, ''))}
                    style={{ border: 'none', outline: 'none', background: 'transparent', width: '100%', textAlign: 'left', padding: '0 2px 0 7px', fontSize: 12.5, color: overridden ? 'var(--accent)' : 'var(--ink)', height: '100%' }} />
                  <span style={{ padding: '0 6px 0 0', color: 'var(--faint)', fontSize: 11 }}>%</span>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </Card>
  );
}

/* ───────────── Acquisition Financing (compact) ───────────── */
function AcqFinancingSection({ deal, set, uw }) {
  const fin = deal.acqFin || { mode: 'none' };
  const mode = fin.mode || 'none';
  const setMode = (label) => {
    const m = label === 'New Loan' ? 'new' : label === 'Assumable' ? 'assumable' : 'none';
    const next = { ...fin, mode: m };
    if (m === 'new' && !next.new) next.new = { basis: 'LTV', pct: 65, rate: 6.0, amYears: 30, ioYears: 0 };
    if (m === 'assumable' && !next.assumable) next.assumable = { origAmount: Math.round((deal.purchasePrice || 0) * 0.6), origDate: '2022-01-01', rate: 4.5, amYears: 30, ioYears: 2, maturity: '2032-01-01' };
    set('acqFin', next);
  };
  const setNew = (k, v) => set('acqFin', { ...fin, new: { ...(fin.new || {}), [k]: v } });
  const setAssum = (k, v) => set('acqFin', { ...fin, assumable: { ...(fin.assumable || {}), [k]: v } });
  const n = fin.new || {}; const a = fin.assumable || {};
  const goingInDSCR = uw.rows[1] && uw.rows[1].ds > 0 ? uw.rows[1].noi / uw.rows[1].ds : null;
  const modeLabel = mode === 'new' ? 'New Loan' : mode === 'assumable' ? 'Assumable' : 'All Cash';

  // Financing scenario presets. Each sets the new-loan terms; "Bridge to HUD" also
  // turns on and configures the HUD takeout refinance.
  const SCENARIOS = {
    'Bridge to HUD':     { loan: { basis: 'LTC', pct: 70, rate: 6.25, amYears: 30, ioYears: 3 },
                           refi: { enabled: true, year: 3, cap: 6, ltv: 80, rate: 6, amYears: 35, ioYears: 0, costPct: 2 } },
    'HUD at Acquisition':    { loan: { basis: 'LTV', pct: 85, rate: 5.75, amYears: 35, ioYears: 0 } },
    'Agency at Acquisition': { loan: { basis: 'LTV', pct: 70, rate: 5.5, amYears: 30, ioYears: 2 } },
    'Custom':            null,
  };
  const applyScenario = (label) => {
    const s = SCENARIOS[label];
    if (!s) { set('acqFin', { ...fin, mode: 'new', scenario: 'Custom' }); return; }
    const next = { ...fin, mode: 'new', scenario: label, new: { ...s.loan } };
    set('acqFin', next);
    if (s.refi) set('refi', { ...(deal.refi || {}), ...s.refi });
  };

  return (
    <Card>
      <SectionHead icon="bank" title="Acquisition Financing" desc="New financing or assumed debt at close."
        right={<Seg size="sm" value={modeLabel} options={['All Cash', 'New Loan', 'Assumable']} onChange={setMode} />} />

      {mode === 'none' && (
        <div style={{ marginTop: 12, padding: '10px 14px', color: 'var(--muted)', fontSize: 12.5, background: 'var(--panel-2)', borderRadius: 7, fontStyle: 'italic' }}>
          All-cash acquisition — equity equals total basis plus closing costs.
        </div>
      )}

      {mode === 'new' && (<>
        <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginTop: 12, marginBottom: 4 }}>
          <span style={{ fontSize: 10.5, fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--muted)', flex: 'none' }}>Scenario</span>
          <select value={fin.scenario || 'Custom'} onChange={(e) => applyScenario(e.target.value)}
            style={{ border: '1px solid var(--line-2)', borderRadius: 7, padding: '6px 10px', background: 'var(--panel)',
              fontSize: 12.5, fontWeight: 600, color: 'var(--accent)', cursor: 'pointer', fontFamily: 'var(--font)' }}>
            {Object.keys(SCENARIOS).map((s) => <option key={s} value={s}>{s}</option>)}
          </select>
          <span style={{ fontSize: 11.5, color: 'var(--faint)' }}>
            {fin.scenario === 'Bridge to HUD' ? 'sets bridge loan + HUD takeout refi' : 'preset terms — adjust any field below'}
          </span>
        </div>
        <CompactGrid>
          <CAssump label="Sizing" hint={n.basis === 'LTC' ? 'on total cost' : 'on price'} w={108}>
            <Seg size="sm" value={n.basis === 'LTC' ? 'LTC' : 'LTV'} options={['LTV', 'LTC']} onChange={(v) => setNew('basis', v)} />
          </CAssump>
          <CAssump label={n.basis === 'LTC' ? 'Loan to Cost' : 'Loan to Value'}><FieldInput value={n.pct == null ? 65 : n.pct} onChange={(v) => setNew('pct', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Interest Rate"><FieldInput value={n.rate == null ? 6 : n.rate} onChange={(v) => setNew('rate', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Amortization"><FieldInput value={n.amYears == null ? 30 : n.amYears} onChange={(v) => setNew('amYears', v)} suffix="yrs" align="left" /></CAssump>
          <CAssump label="Interest-Only"><FieldInput value={n.ioYears == null ? 0 : n.ioYears} onChange={(v) => setNew('ioYears', v)} suffix="yrs" align="left" /></CAssump>
        </CompactGrid>
        <FinFooter uw={uw} goingInDSCR={goingInDSCR} />
      </>)}

      {mode === 'assumable' && (<>
        <CompactGrid>
          <CAssump label="Original Loan" w={150}><FieldInput value={a.origAmount} onChange={(v) => setAssum('origAmount', v || 0)} prefix="$" /></CAssump>
          <CAssump label="Origination" w={140}>{dateBox(a.origDate, (v) => setAssum('origDate', v))}</CAssump>
          <CAssump label="Interest Rate"><FieldInput value={a.rate} onChange={(v) => setAssum('rate', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Amortization"><FieldInput value={a.amYears == null ? 30 : a.amYears} onChange={(v) => setAssum('amYears', v)} suffix="yrs" align="left" /></CAssump>
          <CAssump label="Interest-Only"><FieldInput value={a.ioYears == null ? 0 : a.ioYears} onChange={(v) => setAssum('ioYears', v)} suffix="yrs" align="left" /></CAssump>
          <CAssump label="Maturity" w={140}>{dateBox(a.maturity, (v) => setAssum('maturity', v))}</CAssump>
        </CompactGrid>
        <FinFooter uw={uw} goingInDSCR={goingInDSCR} assumed />
      </>)}
    </Card>
  );
}
function FinFooter({ uw, goingInDSCR, assumed }) {
  const ds1 = uw.acqLoan ? uw.acqLoan.dsForYear(1) : 0;
  return (
    <div style={{ marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 12 }}>
      <FootStat label={assumed ? 'Assumed Balance' : 'Loan Proceeds'} value={moneyFull(uw.acqProceeds)} accent="var(--accent)" />
      <FootStat label="Annual Debt Service" value={moneyFull(ds1)} />
      <FootStat label="Equity Required" value={moneyFull(uw.initialEquity)} sub="incl. closing + capex" />
      <FootStat label="Going-In DSCR" value={goingInDSCR == null ? '—' : goingInDSCR.toFixed(2) + 'x'} accent={goingInDSCR != null && goingInDSCR < 1.2 ? 'var(--neg)' : 'var(--pos)'} />
    </div>
  );
}
function FootStat({ label, value, sub, accent }) {
  return (
    <div>
      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 600, letterSpacing: '.04em', textTransform: 'uppercase', marginBottom: 4 }}>{label}</div>
      <div className="num" style={{ fontSize: 16, fontWeight: 700, color: accent || 'var(--ink)' }}>{value}</div>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--faint)', marginTop: 2 }}>{sub}</div>}
    </div>
  );
}

/* ───────────── Refinance (compact) ───────────── */
function RefiSection({ deal, set, uw }) {
  const refi = deal.refi || { enabled: false };
  const on = !!refi.enabled;
  const setRefi = (k, v) => set('refi', { ...refi, [k]: v });
  const toggle = (label) => {
    if (label === 'Yes') set('refi', { enabled: true, year: refi.year || 3, cap: refi.cap || 6.0, ltv: refi.ltv || 80, rate: refi.rate || 6.0, amYears: refi.amYears || 35, ioYears: refi.ioYears || 0 });
    else set('refi', { ...refi, enabled: false });
  };
  return (
    <Card>
      <SectionHead icon="target" title="Refinance" desc="Cash-out refi during the hold. Value = refi-year NOI ÷ refi cap; proceeds repay the old loan."
        right={<Seg size="sm" value={on ? 'Yes' : 'No'} options={['No', 'Yes']} onChange={toggle} />} />
      {!on ? (
        <div style={{ marginTop: 12, padding: '10px 14px', color: 'var(--muted)', fontSize: 12.5, background: 'var(--panel-2)', borderRadius: 7, fontStyle: 'italic' }}>
          No refinance — acquisition loan carried through to sale.
        </div>
      ) : (<>
        <CompactGrid>
          <CAssump label="Refi Year"><FieldInput value={refi.year == null ? 3 : refi.year} onChange={(v) => setRefi('year', v || 1)} suffix="yr" align="left" /></CAssump>
          <CAssump label="Refi Cap Rate"><FieldInput value={refi.cap} onChange={(v) => setRefi('cap', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Refi LTV" hint="HUD — adjustable"><FieldInput value={refi.ltv == null ? 80 : refi.ltv} onChange={(v) => setRefi('ltv', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Interest Rate"><FieldInput value={refi.rate == null ? 6 : refi.rate} onChange={(v) => setRefi('rate', v)} suffix="%" align="left" /></CAssump>
          <CAssump label="Amortization" hint="HUD — adjustable"><FieldInput value={refi.amYears == null ? 35 : refi.amYears} onChange={(v) => setRefi('amYears', v)} suffix="yrs" align="left" /></CAssump>
          <CAssump label="Interest-Only"><FieldInput value={refi.ioYears == null ? 0 : refi.ioYears} onChange={(v) => setRefi('ioYears', v)} suffix="yrs" align="left" /></CAssump>
          <CAssump label="Refi Cost" hint="% of new loan"><FieldInput value={refi.costPct == null ? 2 : refi.costPct} onChange={(v) => setRefi('costPct', v)} suffix="%" align="left" /></CAssump>
        </CompactGrid>
        <div style={{ marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: 'repeat(5,1fr)', gap: 12 }}>
          <FootStat label={'Refi Value (Yr ' + uw.refiYear + ')'} value={moneyFull(uw.refiValue)} sub="NOI ÷ refi cap" />
          <FootStat label="New Loan" value={moneyFull(uw.refiProceeds)} accent="var(--accent)" />
          <FootStat label="Old Loan Payoff" value={moneyFull(uw.refiPayoff)} />
          <FootStat label="Refi Cost" value={moneyFull(uw.refiCost)} sub={(refi.costPct == null ? 2 : refi.costPct) + '% of loan'} />
          <FootStat label="Cash-Out to Equity" value={moneyFull(uw.refiCashOut)} accent={uw.refiCashOut >= 0 ? 'var(--pos)' : 'var(--neg)'} />
        </div>
      </>)}
    </Card>
  );
}

/* ───────────── Annual Cash Flow table ───────────── */
function CashFlowTable({ uw, showReturns = true }) {
  const cols = uw.rows;
  const colW = 116, labelW = 200;
  const grid = `${labelW}px repeat(${cols.length}, minmax(${colW}px, 1fr))`;
  const headLabel = (y) => y === 0 ? 'Acq Year' : 'Year ' + y;
  const Row = ({ label, hint, get, fmt, strong, accent, neg, top }) => (
    <div style={{ display: 'grid', gridTemplateColumns: grid, alignItems: 'center', borderTop: top ? '1px solid var(--line-2)' : '1px solid var(--line)' }}>
      <div style={{ padding: '9px 14px', position: 'sticky', left: 0, background: 'var(--panel)', zIndex: 1 }}>
        <div style={{ fontSize: 12.5, fontWeight: strong ? 600 : 400, color: 'var(--ink)' }}>{label}</div>
        {hint && <div style={{ fontSize: 10.5, color: 'var(--faint)' }}>{hint}</div>}
      </div>
      {cols.map((r) => {
        const v = get(r); const txt = fmt(v, r);
        const isNeg = neg && typeof v === 'number' && v < 0;
        return <div key={r.year} className="num" style={{ padding: '9px 14px', textAlign: 'right', fontSize: strong ? 13.5 : 12.5, fontWeight: strong ? 700 : 500, color: isNeg ? 'var(--neg)' : (accent || (strong ? 'var(--ink)' : 'var(--slate)')), background: r.year === 0 ? 'var(--panel-2)' : 'transparent' }}>{txt}</div>;
      })}
    </div>
  );
  return (
    <Card pad={false}>
      <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <span style={{ width: 30, height: 30, borderRadius: 7, background: 'var(--navy)', color: '#fff', flex: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="chart" size={15} /></span>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)' }}>Annual Cash Flow</div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>{uw.hold}-year hold · acquisition year + {uw.hold} years · sale at end of year {uw.hold}</div>
        </div>
      </div>
      <div style={{ overflowX: 'auto' }}>
        <div style={{ minWidth: labelW + cols.length * colW }}>
          <div style={{ display: 'grid', gridTemplateColumns: grid, background: 'var(--panel-3)', borderBottom: '1px solid var(--line)' }}>
            <div style={{ padding: '9px 14px', position: 'sticky', left: 0, background: 'var(--panel-3)', zIndex: 2, fontSize: 10.5, fontWeight: 700, letterSpacing: '.05em', textTransform: 'uppercase', color: 'var(--muted)' }}>Line Item</div>
            {cols.map((r) => <div key={r.year} style={{ padding: '9px 14px', textAlign: 'right', fontSize: 11.5, fontWeight: 700, color: r.year === 0 ? 'var(--accent)' : 'var(--ink)' }}>{headLabel(r.year)}</div>)}
          </div>
          <Row label="Effective Gross Income" get={(r) => r.egi} fmt={moneyFull} />
          <Row label="Operating Expenses" get={(r) => -r.opex} fmt={(v) => moneyFull(v)} neg />
          <Row label="Net Operating Income" get={(r) => r.noi} fmt={moneyFull} strong />
          <Row label="Debt Service" get={(r) => (r.ds ? -r.ds : 0)} fmt={(v) => (v ? moneyFull(v) : '—')} neg />
          <Row label="Asset Management Fee" hint={'on EGI'} get={(r) => (r.amFee ? -r.amFee : 0)} fmt={(v) => (v ? moneyFull(v) : '—')} neg />
          <Row label="Net Cash Flow" hint="NOI − debt service − AM fee" get={(r) => r.netIncome} fmt={moneyFull} strong accent="var(--accent)" neg />
          {uw.refiOn && <Row label="Return of Capital (Refi)" hint={'cash-out, year ' + uw.refiYear} get={(r) => r.refiDistribution} fmt={(v) => (v ? moneyFull(v) : '—')} accent="var(--navy)" />}
          <Row label="Net Sale Proceeds" hint={'at exit, year ' + uw.hold} get={(r) => r.saleProceeds} fmt={(v) => (v ? moneyFull(v) : '—')} accent="var(--navy)" />
          <Row label="Total Cash Flow to Equity" hint="net CF + refi ROC + sale" get={(r) => r.totalCashFlow} fmt={moneyFull} strong accent="var(--pos)" neg />
          <Row top label="Net Revenue Growth" hint="YoY EGI Δ · rent growth + vacancy" get={(r) => r.netRevGrowth} fmt={(v) => (v == null ? '—' : (v >= 0 ? '+' : '') + (v * 100).toFixed(1) + '%')} />
          <Row label="Yield on Cost" hint="NOI ÷ total basis" get={(r) => r.yieldOnCost} fmt={pct1} />
          <Row label="DSCR" hint="NOI ÷ debt service" get={(r) => r.dscr} fmt={(v) => (v == null ? '—' : v.toFixed(2) + 'x')} />
          <Row label="Cash-on-Cash Yield" hint="net CF ÷ equity balance" get={(r) => r.cashOnCash} fmt={(v) => (v == null ? '—' : pct1(v))} />
          <Row label="Principal Paydown" hint="amortization ÷ equity balance" get={(r) => r.principalPaydownPct} fmt={(v) => (v == null || v === 0 ? '—' : pct1(v))} />
          <Row label="Yield + Principal Paydown" hint="cash yield + paydown" get={(r) => r.yieldPlusPaydown} fmt={(v) => (v == null ? '—' : pct1(v))} strong accent="var(--pos)" />
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5,1fr)', borderTop: '1px solid var(--line)' }}>
        <SumCell label="Equity Invested" value={moneyFull(uw.initialEquity)} />
        <SumCell label={'Exit Value (Yr ' + uw.hold + ')'} value={showReturns && uw.salePrice ? moneyFull(uw.salePrice) : '—'} sub={uw.exitCap ? pct1(uw.exitCap) + ' exit cap' : 'set exit cap'} />
        <SumCell label="Net Sale Proceeds" value={showReturns && uw.salePrice ? moneyFull(uw.netSaleProceeds) : '—'} />
        <SumCell label="Equity Multiple" value={showReturns && uw.equityMultiple != null ? uw.equityMultiple.toFixed(2) + 'x' : '—'} accent="var(--ink)" />
        <SumCell label="Levered IRR" value={showReturns && uw.irr != null ? (uw.irr * 100).toFixed(1) + '%' : '—'} accent={showReturns && uw.irr != null ? 'var(--pos)' : 'var(--faint)'} big />
      </div>
    </Card>
  );
}
function SumCell({ label, value, sub, accent, big }) {
  return (
    <div style={{ padding: '16px 18px', borderLeft: '1px solid var(--line)' }}>
      <div style={{ fontSize: 10.5, color: 'var(--muted)', fontWeight: 600, letterSpacing: '.05em', textTransform: 'uppercase', marginBottom: 8 }}>{label}</div>
      <div className="num" style={{ fontSize: big ? 26 : 20, fontWeight: 700, color: accent || 'var(--ink)', lineHeight: 1 }}>{value}</div>
      {sub && <div style={{ fontSize: 11, color: 'var(--faint)', marginTop: 6 }}>{sub}</div>}
    </div>
  );
}

/* ───────────── Quick & Full tabs ───────────── */
function CapCards({ deal, set, m }) {
  const capDelta = m.stabilizedCap - m.goingInCap;
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, alignItems: 'start' }}>
      <Card>
        <SectionHead icon="target" title="Going-In Cap Rate" desc="In-place EGI vs. our per-unit expense assumption." />
        <div style={{ marginTop: 10 }}>
          <CalcRow kind="INPUT" label="Effective Gross Income" hint="in-place · from OM"><FieldInput value={deal.trailingEGI} onChange={(v) => set('trailingEGI', v || 0)} prefix="$" /></CalcRow>
          <CalcRow kind="INPUT" label="T-12 Operating Expenses" hint="total, in-place · from OM"><FieldInput value={deal.currentOpexTotal} onChange={(v) => set('currentOpexTotal', v || 0)} prefix="$" /></CalcRow>
          <CalcRow kind="OUTPUT" label="Current OpEx / Unit" hint={fmtNum(m.units) + ' units'}>{fmtMoney(m.currentOpexPerUnit)}</CalcRow>
          <CalcRow kind="INPUT" label="Assumption OpEx / Unit" hint="UW assumption"><FieldInput value={deal.marketOpexPerUnit} onChange={(v) => set('marketOpexPerUnit', v || 0)} prefix="$" /></CalcRow>
          <CalcRow kind="OUTPUT" label="Pro Forma OpEx" hint="assumption × units">{fmtMoney(m.marketOpex)}</CalcRow>
          <CalcRow kind="OUTPUT" label="Going-In NOI" hint="EGI − assumption opex" strong>{fmtMoney(m.goingInNOI)}</CalcRow>
          <CalcRow kind="OUTPUT" label="Going-In Cap Rate" hint="NOI ÷ purchase price" strong accent="var(--accent)">{fmtPct(m.goingInCap)}</CalcRow>
        </div>
      </Card>
      <Card>
        <SectionHead icon="pulse" title="Stabilized Cap Rate" desc="Broker EGI vs. market expenses over total basis." />
        <div style={{ marginTop: 10 }}>
          <CalcRow kind="INPUT" label="Broker / Pro Forma EGI" hint="stabilized projection"><FieldInput value={deal.brokerEGI} onChange={(v) => set('brokerEGI', v || 0)} prefix="$" /></CalcRow>
          <CalcRow kind="OUTPUT" label="Our Market Expenses" hint="same UW assumption">{fmtMoney(m.marketOpex)}</CalcRow>
          <CalcRow kind="OUTPUT" label="Pro Forma NOI" strong>{fmtMoney(m.proformaNOI)}</CalcRow>
          <CalcRow kind="OUTPUT" label="Total Basis" hint="price + CapEx">{fmtMoney(m.totalBasis)}</CalcRow>
          <CalcRow kind="OUTPUT" label="Stabilized Cap Rate" hint="NOI ÷ total basis" strong accent="var(--pos)">{fmtPct(m.stabilizedCap)}</CalcRow>
          <div style={{ marginTop: 12, padding: '10px 13px', background: 'var(--panel-2)', borderRadius: 7, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <span style={{ fontSize: 12.5, color: 'var(--slate)', fontWeight: 400 }}>Spread, going-in → stabilized</span>
            <span className="num" style={{ fontSize: 14, fontWeight: 700, color: capDelta >= 0 ? 'var(--pos)' : 'var(--neg)' }}>{capDelta >= 0 ? '+' : ''}{Math.round(capDelta * 10000)} bps</span>
          </div>
        </div>
      </Card>
    </div>
  );
}

function QuickUnderwritingTab({ deal, set }) {
  const m = computeMetrics(deal);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <PricingBasis deal={deal} set={set} m={m} />
      <CapCards deal={deal} set={set} m={m} />
    </div>
  );
}

function FullUnderwritingTab({ deal, set }) {
  const m = computeMetrics(deal);
  const uw = computeUW(deal);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <PricingBasis deal={deal} set={set} m={m} />
      <IncomeVacancySection deal={deal} set={set} />
      <AcqFinancingSection deal={deal} set={set} uw={uw} />
      <RefiSection deal={deal} set={set} uw={uw} />
      <AssumptionsSection deal={deal} set={set} uw={uw} />
      <CashFlowTable uw={uw} showReturns={computeUW && window.hasUWInputs ? window.hasUWInputs(deal) : true} />
    </div>
  );
}

/* ───────────── T-12 parsed banner ───────────── */
function T12ParsedSection({ parsed, onAccept }) {
  const [dismissed, setDismissed] = useSU(false);
  if (dismissed) return null;
  const F = [
    { key: 'badDebt', label: 'Bad Debt / Delinquency', patch: (v) => ({ badDebt: Number(v) || 0 }) },
    { key: 'concessions', label: 'Concessions', patch: (v) => ({ concessions: Number(v) || 0 }) },
    { key: 'totalOpex', label: 'Total Operating Expenses', patch: (v) => ({ currentOpexTotal: Number(v) || 0 }) },
    { key: 'effectiveGrossIncome', label: 'Effective Gross Income', patch: (v) => ({ trailingEGI: Number(v) || 0 }) },
    { key: 'otherIncome', label: 'Other Income', patch: (v) => ({ otherIncome: Number(v) || 0 }) },
  ];
  const money = (v) => (v != null && v !== '') ? '$' + Number(v).toLocaleString() : null;
  const found = F.filter((f) => parsed[f.key] != null && parsed[f.key] !== '');
  const missing = F.filter((f) => parsed[f.key] == null || parsed[f.key] === '');
  const applyAll = () => { let p = {}; found.forEach((f) => { p = { ...p, ...f.patch(parsed[f.key]) }; }); onAccept(p); };
  return (
    <BannerShell title="T-12 parsed" sub={'Pulled ' + found.length + ' figure' + (found.length === 1 ? '' : 's') + ' from the trailing-12 statement'}
      canApply={found.length > 0} onApplyAll={applyAll} onDismiss={() => setDismissed(true)}>
      {found.map((f) => <FoundRow key={f.key} label={f.label} display={money(parsed[f.key])} onUse={() => onAccept(f.patch(parsed[f.key]))} />)}
      {missing.map((f) => <MissingRow key={f.key} label={f.label} />)}
    </BannerShell>
  );
}

/* ───────────── Rent Roll parsed banner ───────────── */
function RentRollParsedSection({ parsed, onAccept }) {
  const [dismissed, setDismissed] = useSU(false);
  if (dismissed) return null;
  const money = (v) => (v != null && v !== '') ? '$' + Number(v).toLocaleString() : null;
  const F = [
    { key: 'gprAnnual', label: 'Gross Potential Rent (annual)', disp: money, patch: (v) => ({ gprAnnual: Number(v) || 0 }) },
    { key: 'physVacLoss', label: 'Physical Vacancy Loss (annual)', disp: money, patch: (v) => ({ physVacLoss: Number(v) || 0 }) },
    { key: 'lossToLease', label: 'Loss to Lease (annual)', disp: money, patch: (v) => ({ lossToLease: Number(v) || 0 }) },
    { key: 'units', label: 'Units', disp: (v) => fmtNum(v), patch: (v) => ({ units: Number(v) || 0 }) },
  ];
  const found = F.filter((f) => parsed[f.key] != null && parsed[f.key] !== '');
  const applyAll = () => { let p = {}; found.forEach((f) => { p = { ...p, ...f.patch(parsed[f.key]) }; }); onAccept(p); };
  const vacPct = parsed.totalUnits ? (parsed.vacantUnits / parsed.totalUnits) : null;
  return (
    <BannerShell title="Rent Roll parsed"
      sub={(parsed.totalUnits ? parsed.totalUnits + ' units · ' : '') + (vacPct != null ? (vacPct * 100).toFixed(1) + '% physical vacancy' : '')}
      canApply={found.length > 0} onApplyAll={applyAll} onDismiss={() => setDismissed(true)}>
      {found.map((f) => <FoundRow key={f.key} label={f.label} display={f.disp(parsed[f.key])} onUse={() => onAccept(f.patch(parsed[f.key]))} />)}
    </BannerShell>
  );
}

Object.assign(window, { QuickUnderwritingTab, FullUnderwritingTab, T12ParsedSection, RentRollParsedSection });
