// ════════════════════════════════════════════════════════════════════════
// PropMystro · Owners (faithful rebuild) · pm-d-owners.jsx
// Ported from the Apps Script pm-owners.jsx:
//   • People — owner cards (solo / joint counts + monthly share)
//   • Joint holdings — split bars per jointly-owned property
//   • Owner detail — hero, compliance across involved properties, finance
//     share, full portfolio table (stake % + share/mo + status)
//   • Edit modal — contact + tax (UTR / MTD) + bank details
// Rent share = solo rent for primary-only; for joint props, split_pct from
// property_owners. Gated by owner_cap (Starter 1 · Pro 2 · Portfolio ∞).
// → window.PMOwners
// ════════════════════════════════════════════════════════════════════════
(function () {
  const { useState, useEffect, useCallback } = React;

  const SWATCHES = ['#385a8a', '#4f7a3a', '#8a5a2a', '#6a4a8a', '#b8392a', '#2a7a6a'];
  const initials = (s) => (s || '?').trim().split(/\s+/).map(w => w[0]).slice(0, 2).join('').toUpperCase();
  const money = (n) => '£' + Math.round(Number(n || 0)).toLocaleString('en-GB');
  const slugKey = (name) => (name.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '').slice(0, 16) || 'owner') + '_' + Math.random().toString(36).slice(2, 6);
  const daysU = (d) => d ? Math.ceil((new Date(d) - new Date()) / 86400000) : null;
  const CORE = ['gas_safety', 'eicr', 'epc'];
  function propHealth(certs) {
    let worst = 'ok';
    CORE.forEach(type => {
      const c = certs.filter(x => x.type === type && x.expiry_date).sort((a, b) => new Date(b.expiry_date) - new Date(a.expiry_date))[0];
      if (!c) { if (worst === 'ok') worst = 'warn'; return; }
      const d = daysU(c.expiry_date);
      if (d < 0) worst = 'crit'; else if (d <= 60 && worst !== 'crit') worst = 'warn';
    });
    return worst;
  }

  function Spin() { return <span className="spin dark" />; }

  // builds the owner-involvement model from properties + property_owners
  function buildModel(owners, props, po) {
    // jointMap: property_id -> [{owner_id, split_pct}] (incl primary), ordered primary-first
    const byProp = {};
    po.forEach(r => { (byProp[r.property_id] = byProp[r.property_id] || []).push(r); });
    const involve = {};   // owner_id -> { solo:[], joint:[], share }
    owners.forEach(o => { involve[o.id] = { solo: [], joint: [], share: 0 }; });
    props.forEach(p => {
      const links = byProp[p.id] || [];
      const isJoint = links.length > 1;
      if (isJoint) {
        links.forEach(l => {
          if (!involve[l.owner_id]) return;
          const pct = l.split_pct != null ? Number(l.split_pct) : Math.round(100 / links.length);
          involve[l.owner_id].joint.push({ p, pct });
          involve[l.owner_id].share += (p.rent || 0) * pct / 100;
        });
      } else if (p.primary_owner_id && involve[p.primary_owner_id]) {
        involve[p.primary_owner_id].solo.push({ p, pct: 100 });
        involve[p.primary_owner_id].share += (p.rent || 0);
      }
    });
    return { byProp, involve };
  }

  function Owners({ sb, account, toast, onUpgrade, onOpenProperty }) {
    const [sub, setSub] = useState('people');
    const [owners, setOwners] = useState(null);
    const [props, setProps] = useState([]);
    const [po, setPo] = useState([]);
    const [certs, setCerts] = useState([]);
    const [detail, setDetail] = useState(null);   // owner id
    const [editing, setEditing] = useState(null);  // owner obj | 'new'

    const cap = account.owner_cap != null ? account.owner_cap : (account.plan === 'portfolio' ? 100000 : account.plan === 'professional' ? 2 : 1);
    const capLabel = cap >= 100000 ? '∞' : cap;
    const nextTier = account.plan === 'starter' ? 'Professional (2 owners)' : 'Portfolio (unlimited owners)';

    const load = useCallback(async () => {
      const [o, p, pol, c] = await Promise.all([
        sb.from('owners').select('*').order('created_at', { ascending: true }),
        sb.from('properties').select('id,address,postcode,type,rent,primary_owner_id'),
        sb.from('property_owners').select('property_id,owner_id,split_pct'),
        sb.from('certificates').select('property_id,type,expiry_date'),
      ]);
      setOwners(o.data || []); setProps(p.data || []); setPo(pol.data || []); setCerts(c.data || []);
    }, [sb]);
    useEffect(() => { load(); }, [load]);

    if (owners === null) return <div className="card card-pad"><Spin /></div>;

    const { involve } = buildModel(owners, props, po);
    const jointProps = props.filter(p => (po.filter(r => r.property_id === p.id).length > 1));
    const certsForProp = (id) => certs.filter(c => c.property_id === id);
    const atCap = owners.length >= cap;

    // ── owner detail ──
    if (detail) {
      const o = owners.find(x => x.id === detail); if (!o) { setDetail(null); return null; }
      const inv = involve[o.id] || { solo: [], joint: [], share: 0 };
      const all = [...inv.solo.map(x => ({ ...x, mode: 'solo' })), ...inv.joint.map(x => ({ ...x, mode: 'joint' }))];
      let crit = 0, warn = 0, ok = 0;
      all.forEach(({ p }) => { const h = propHealth(certsForProp(p.id)); if (h === 'crit') crit++; else if (h === 'warn') warn++; else ok++; });
      return <React.Fragment>
        <button className="backlink" onClick={() => setDetail(null)}>← Back to owners</button>
        <div className="owner-hero">
          <span className="owner-hero-av" style={{ background: o.color || '#385a8a' }}>{initials(o.name)}</span>
          <div style={{ flex: 1 }}>
            <h1>{o.name}{o.is_primary ? <span className="pm-primary-tag">primary</span> : ''}</h1>
            <p>{[o.email, o.phone, o.utr ? 'UTR ' + o.utr : null].filter(Boolean).join(' · ') || 'No contact details'}{o.mtd_enrolled ? ' · MTD enrolled' : ''}</p>
          </div>
          <div className="owner-hero-kpis">
            <div><span className="n">{all.length}</span><span className="l">properties</span></div>
            <div><span className="n">{money(inv.share)}</span><span className="l">share/mo</span></div>
            <button className="btn btn-ghost btn-sm" onClick={() => setEditing(o)}>Edit details</button>
          </div>
        </div>

        <div className="ov-grid" style={{ marginBottom: 16 }}>
          <div className="ov-card">
            <h4>Compliance across {all.length} {all.length === 1 ? 'property' : 'properties'}</h4>
            <div className="mini-kpis">
              <div className={'mini-kpi' + (crit ? ' crit' : '')}><span className="n">{crit}</span><span className="l">critical</span></div>
              <div className={'mini-kpi' + (warn ? ' warn' : '')}><span className="n">{warn}</span><span className="l">warning</span></div>
              <div className={'mini-kpi' + (ok ? ' ok' : '')}><span className="n">{ok}</span><span className="l">healthy</span></div>
            </div>
          </div>
          <div className="ov-card">
            <h4>Finance · this owner's share</h4>
            <div className="dl">
              <dt>Solo properties</dt><dd>{inv.solo.length}</dd>
              <dt>Joint properties</dt><dd>{inv.joint.length}</dd>
              <dt>Monthly share</dt><dd>{money(inv.share)}</dd>
              <dt>Annualised</dt><dd>{money(inv.share * 12)}</dd>
            </div>
          </div>
        </div>

        <div className="card">
          <div className="card-head"><div><h3>Portfolio · {all.length} {all.length === 1 ? 'property' : 'properties'}</h3></div></div>
          {all.length === 0 ? <div className="empty" style={{ padding: '26px' }}><p style={{ color: 'var(--ink-faint)' }}>No properties linked to this owner yet.</p></div>
          : <div style={{ overflowX: 'auto' }}><table className="prop-table">
            <thead><tr><th>Property</th><th>Type</th><th>Stake</th><th>Share/mo</th><th>Status</th><th></th></tr></thead>
            <tbody>{all.map(({ p, pct, mode }) => { const h = propHealth(certsForProp(p.id)); return <tr key={p.id} className="clickable" onClick={() => onOpenProperty && onOpenProperty(p)}>
              <td><div className="prop-addr">{p.address}</div><div className="prop-meta">{p.postcode}</div></td>
              <td className="pmd-mono" style={{ fontSize: 12 }}>{(p.type || '—').toUpperCase()}</td>
              <td className="pmd-mono" style={{ fontSize: 12 }}>{mode === 'solo' ? 'solo' : pct + '%'}</td>
              <td>{money((p.rent || 0) * (pct / 100))}</td>
              <td><span className={'hdot ' + h}></span><span className="pmd-mono" style={{ fontSize: 11, color: h === 'crit' ? 'var(--red)' : h === 'warn' ? 'var(--amber)' : 'var(--ok)' }}>{h.toUpperCase()}</span></td>
              <td><span style={{ color: 'var(--ink-faint)' }}>→</span></td>
            </tr>; })}</tbody>
          </table></div>}
        </div>
        {editing && <EditModal sb={sb} account={account} owner={editing === 'new' ? null : editing} onClose={() => setEditing(null)} onSaved={() => { setEditing(null); load(); }} toast={toast} />}
      </React.Fragment>;
    }

    // ── hub ──
    return <React.Fragment>
      <div className="pagehead" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, flexWrap: 'wrap' }}>
        <div><h1>Owners</h1><p>The people and companies that own your properties. Click an owner for their portfolio &amp; share.</p></div>
        {atCap ? <button className="btn btn-ghost btn-sm" onClick={() => onUpgrade && onUpgrade()}>↑ Upgrade for more owners</button>
          : <button className="btn btn-primary btn-sm" onClick={() => setEditing('new')}>+ Add owner</button>}
      </div>

      <div className="pm-seg" style={{ marginBottom: 16 }}>
        <button className={'pm-seg-btn' + (sub === 'people' ? ' on' : '')} onClick={() => setSub('people')}>People <span className="pmd-mono" style={{ opacity: .6 }}>· {owners.length}</span></button>
        <button className={'pm-seg-btn' + (sub === 'joint' ? ' on' : '')} onClick={() => setSub('joint')}>Joint holdings <span className="pmd-mono" style={{ opacity: .6 }}>· {jointProps.length}</span></button>
      </div>

      {atCap && <div className="alert alert-info" style={{ marginBottom: 14 }}><span className="ic">🔒</span><div>You've reached your plan's owner limit ({capLabel}). Multi-owner portfolios — co-owners, joint splits, per-owner shares — are a <b>{nextTier}</b> feature. {onUpgrade && <button className="linkbtn" onClick={onUpgrade}>Upgrade →</button>}</div></div>}

      {sub === 'people' ? (owners.length === 0 ? <div className="card"><div className="empty"><div className="ico">👤</div><h3>No owners yet</h3><p>Add the people or companies that own your properties. Their details feed Tax and rent reviews.</p><button className="btn btn-primary btn-sm" onClick={() => setEditing('new')}>+ Add an owner</button></div></div>
        : <div className="owner-grid">{owners.map(o => { const inv = involve[o.id] || { solo: [], joint: [], share: 0 }; return <div key={o.id} className="owner-card" onClick={() => setDetail(o.id)}>
          <div className="owner-card-head"><span className="avatar" style={{ background: (o.color || '#385a8a') + '22', color: o.color || '#385a8a' }}>{initials(o.name)}</span><div style={{ flex: 1 }}><div className="t">{o.name}{o.is_primary ? <span className="pm-primary-tag">primary</span> : ''}</div><div className="s">{o.email || 'No email'}</div></div>{o.mtd_enrolled && <span className="badge ok">MTD</span>}</div>
          <div className="owner-card-stats"><div><span className="osn">{inv.solo.length}</span><span className="osl">solo</span></div><div><span className="osn">{inv.joint.length}</span><span className="osl">joint</span></div><div><span className="osn">{money(inv.share)}</span><span className="osl">share/mo</span></div></div>
        </div>; })}</div>)
      : /* joint */ (jointProps.length === 0 ? <div className="card"><div className="empty"><div className="ico">🤝</div><h3>No joint holdings</h3><p>All properties are solo-owned. Add co-owners to a property (and split percentages) to see them here.</p></div></div>
        : <div className="joint-list">{jointProps.map(p => { const links = po.filter(r => r.property_id === p.id); const ordered = [...links].sort((a, b) => (a.owner_id === p.primary_owner_id ? -1 : 1)); return <div key={p.id} className="card joint-card" onClick={() => onOpenProperty && onOpenProperty(p)}>
          <div className="card-head"><div><h3>{p.address}</h3><div className="sub">{p.postcode} · {money(p.rent)}/mo total</div></div><span style={{ color: 'var(--ink-faint)' }}>→</span></div>
          <div className="card-pad">{ordered.map((l, i) => { const o = owners.find(x => x.id === l.owner_id) || { name: 'Unknown', color: '#9a8f80' }; const pct = l.split_pct != null ? Number(l.split_pct) : Math.round(100 / links.length); return <div key={l.owner_id} className="joint-split">
            <span className="owner-dot" style={{ background: o.color }}></span><strong style={{ minWidth: 110 }}>{o.name}</strong>{l.owner_id === p.primary_owner_id && <span className="pm-primary-tag">primary</span>}
            <div className="split-bar"><div className="split-bar-fill" style={{ width: pct + '%', background: o.color }}></div></div>
            <span className="pmd-mono" style={{ fontSize: 12, minWidth: 38, textAlign: 'right' }}>{pct}%</span>
            <span className="pmd-mono" style={{ fontSize: 12, color: 'var(--ink-faint)', minWidth: 70, textAlign: 'right' }}>{money((p.rent || 0) * pct / 100)}/mo</span>
          </div>; })}</div>
        </div>; })}</div>)}

      {editing && <EditModal sb={sb} account={account} owner={editing === 'new' ? null : editing} onClose={() => setEditing(null)} onSaved={() => { setEditing(null); load(); }} toast={toast} />}
    </React.Fragment>;
  }

  // ── Edit / add owner modal ─────────────────────────────────────────────
  function EditModal({ sb, account, owner, onClose, onSaved, toast }) {
    const editing = !!owner;
    const [d, setD] = useState(owner ? {
      name: owner.name || '', email: owner.email || '', phone: owner.phone || '', address: owner.address || '',
      utr: owner.utr || '', mtd_enrolled: !!owner.mtd_enrolled, is_primary: !!owner.is_primary,
      bank_sort_code: owner.bank_sort_code || '', bank_account: owner.bank_account || '', color: owner.color || SWATCHES[0],
    } : { name: '', email: '', phone: '', address: '', utr: '', mtd_enrolled: false, is_primary: false, bank_sort_code: '', bank_account: '', color: SWATCHES[0] });
    const [busy, setBusy] = useState(false); const [err, setErr] = useState('');
    const set = (k) => (e) => setD({ ...d, [k]: e.target.value });

    const save = async () => {
      setErr(''); if (!d.name.trim()) return setErr('Name is required.');
      setBusy(true);
      const patch = { name: d.name.trim(), email: d.email.trim() || null, phone: d.phone.trim() || null, address: d.address.trim() || null, utr: d.utr.trim() || null, mtd_enrolled: d.mtd_enrolled, is_primary: d.is_primary, bank_sort_code: d.bank_sort_code.trim() || null, bank_account: d.bank_account.trim() || null, color: d.color };
      let error;
      if (editing) ({ error } = await sb.from('owners').update(patch).eq('id', owner.id));
      else ({ error } = await sb.from('owners').insert({ account_id: account.id, key: slugKey(d.name), ...patch }));
      setBusy(false);
      if (error) return setErr(/owner_cap/.test(error.message) ? 'You\'ve reached your plan\'s owner limit — upgrade to add more.' : error.message);
      toast(editing ? 'Owner updated' : 'Owner added'); onSaved();
    };

    return <div className="modal-scrim" onClick={onClose}>
      <div className="modal prop-modal" onClick={e => e.stopPropagation()}>
        <div className="modal-head"><div><h2>{editing ? 'Edit owner' : 'Add owner'}</h2><p className="modal-sub">Contact, tax &amp; bank details — these feed every screen, tenancy agreements and rent collection.</p></div><button className="x" onClick={onClose}>✕</button></div>
        {err && <div style={{ padding: '0 24px' }}><div className="alert alert-err"><span className="ic">⚠</span><div>{err}</div></div></div>}
        <div className="modal-form">
          <div className="field full"><label>Full name</label><input value={d.name} onChange={set('name')} placeholder="Alpa Desai" /></div>
          <div className="field"><label>Email</label><input value={d.email} onChange={set('email')} placeholder="alpa@example.com" /></div>
          <div className="field"><label>Phone</label><input value={d.phone} onChange={set('phone')} placeholder="optional" /></div>
          <div className="field full"><label>Address</label><input value={d.address} onChange={set('address')} placeholder="Correspondence address" /></div>
          <div className="field"><label>UTR (tax reference)</label><input value={d.utr} onChange={e => setD({ ...d, utr: e.target.value.replace(/[^\d ]/g, '') })} placeholder="10-digit UTR" /></div>
          <div className="field"><label>Bank sort code</label><input value={d.bank_sort_code} onChange={set('bank_sort_code')} placeholder="00-00-00" /></div>
          <div className="field"><label>Bank account no.</label><input value={d.bank_account} onChange={set('bank_account')} placeholder="8 digits" /></div>
          <div className="field"><label>Colour</label><div className="swatches" style={{ marginTop: 4 }}>{SWATCHES.map(c => <button key={c} type="button" className={'sw' + (d.color === c ? ' on' : '')} style={{ background: c }} onClick={() => setD({ ...d, color: c })} />)}</div></div>
          <div className="field"><label>MTD-ITSA</label><button type="button" className={'pm-toggle' + (d.mtd_enrolled ? ' on' : '')} onClick={() => setD({ ...d, mtd_enrolled: !d.mtd_enrolled })}>{d.mtd_enrolled ? '✓ enrolled' : 'not enrolled'}</button></div>
          <div className="field"><label>Primary owner</label><button type="button" className={'pm-toggle' + (d.is_primary ? ' on' : '')} onClick={() => setD({ ...d, is_primary: !d.is_primary })}>{d.is_primary ? '✓ primary' : 'not primary'}</button></div>
        </div>
        <div className="modal-foot" style={{ justifyContent: 'flex-start' }}>
          <button className="btn btn-primary" style={{ width: 'auto' }} onClick={save} disabled={busy}>{busy ? <Spin /> : (editing ? 'Save details' : 'Add owner')}</button>
          <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
        </div>
      </div>
    </div>;
  }

  window.PMOwners = Owners;
})();
