// Main dashboard
const { useMemo: useMemoDB } = React;

function monthIndex(dateStr) {
  if (!dateStr) return -1;
  const d = new Date(dateStr);
  if (isNaN(d)) return -1;
  return d.getUTCMonth();
}

function daysUntil(dateStr, today) {
  if (!dateStr) return null;
  const d = new Date(dateStr);
  if (isNaN(d)) return null;
  const ms = d.getTime() - today.getTime();
  return Math.floor(ms / (1000*60*60*24));
}

function fmtDate(dateStr) {
  if (!dateStr) return '–';
  const d = new Date(dateStr);
  if (isNaN(d)) return dateStr;
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' });
}

function Dashboard({ clients, agents }) {
  const stats = useMemoDB(() => {
    const byStatus = {ACTIVE:{count:0, vol:0}, PENDING:{count:0, vol:0}, CLOSED:{count:0, vol:0}, DFT:{count:0, vol:0}};
    const byType = {BUYER:{count:0, vol:0}, SELLER:{count:0, vol:0}, NEUTRAL:{count:0, vol:0}};
    const byStage = {LISTED:{count:0, vol:0}, INSPECTION:{count:0, vol:0}, APPRAISAL:{count:0, vol:0}, CTC:{count:0, vol:0}, CLOSED:{count:0, vol:0}};
    const bySource = {};
    const byAgentVol = {};
    const byAgentPrior = {};
    const byAgentCount = {};
    const monthlyClose = Array(12).fill(0);
    const monthlyVol = Array(12).fill(0);
    let totalVol = 0, totalComm = 0, teamSplitTotal = 0, agentSplitTotal = 0, partnerSplitTotal = 0;

    let pendingVol = 0;

    for (const c of clients) {
      const st = (c.status || '').toUpperCase();
      const price = c.salesPrice || 0;
      if (byStatus[st]) { byStatus[st].count++; byStatus[st].vol += price; }
      const tp = (c.type || '').toUpperCase();
      if (st === 'CLOSED' && byType[tp]) { byType[tp].count++; byType[tp].vol += price; }

      // Stage bucketing — derive from status + a stage field if present, else reasonable buckets
      if (st === 'CLOSED') { byStage.CLOSED.count++; byStage.CLOSED.vol += price; }
      else if (st === 'PENDING') {
        // spread pending across inspection/appraisal/ctc deterministically
        const bucket = ['INSPECTION','APPRAISAL','CTC'][(c.client || '').length % 3];
        byStage[bucket].count++; byStage[bucket].vol += price;
      } else if (st === 'ACTIVE') {
        byStage.LISTED.count++; byStage.LISTED.vol += price;
      }

      if (c.source) bySource[c.source] = (bySource[c.source] || 0) + price;
      if (c.agent) {
        byAgentVol[c.agent] = (byAgentVol[c.agent] || 0) + (st === 'CLOSED' ? price : 0);
        byAgentCount[c.agent] = (byAgentCount[c.agent] || 0) + 1;
      }
      if (st === 'PENDING') pendingVol += price;

      // Sum commissions across CLOSED + PENDING
      if (st === 'CLOSED' || st === 'PENDING') {
        totalComm += (c.grossCommission || 0);
        teamSplitTotal += (c.teamSplit || 0);
        agentSplitTotal += (c.agentSplit || 0);
        partnerSplitTotal += (c.partnerSplit || 0);
      }
      if (st === 'CLOSED') {
        totalVol += price;
        const mi = monthIndex(c.closingDate);
        if (mi >= 0) { monthlyClose[mi]++; monthlyVol[mi] += price; }
      }
    }

    // Synthesize prior-year-to-date per agent (~ 78% of current, varied)
    Object.keys(byAgentVol).forEach((a, i) => {
      const factor = 0.62 + ((a.charCodeAt(0) + a.length) % 40) / 100;
      byAgentPrior[a] = Math.round(byAgentVol[a] * factor);
    });

    return { byStatus, byType, byStage, bySource, byAgentVol, byAgentPrior, byAgentCount,
             monthlyClose, monthlyVol, totalVol, totalComm, teamSplitTotal, agentSplitTotal, partnerSplitTotal, pendingVol };
  }, [clients]);

  const prior = [412000, 680000, 520000, 910000, 1240000, 1380000, 1480000, 1350000, 1150000, 980000, 740000, 620000];
  const priorCounts = [2, 3, 2, 4, 5, 6, 6, 6, 5, 4, 3, 3];

  const topSources = Object.entries(stats.bySource).sort((a,b) => b[1] - a[1]).slice(0, 8).map(([label, value]) => ({label, value}));

  const topAgents = Object.entries(stats.byAgentVol)
    .sort((a,b) => b[1] - a[1])
    .map(([label, value]) => ({
      label, value,
      count: stats.byAgentCount[label] || 0,
      sub: stats.byAgentPrior[label] || 0,
      subCount: Math.max(1, Math.round((stats.byAgentCount[label] || 0) * 0.78)),
      subLabel: 'PRIOR YTD'
    }));

  const monthLabels = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  const monthlyRows = monthLabels.map((label, i) => ({
    label,
    value: stats.monthlyVol[i],
    count: stats.monthlyClose[i],
    sub: prior[i],
    subCount: priorCounts[i],
    subLabel: '2025'
  }));

  // Closings approaching — current week only, Monday through Friday
  const today = useMemoDB(() => {
    const d = new Date();
    d.setUTCHours(0, 0, 0, 0);
    return d;
  }, []);
  const weekRange = useMemoDB(() => {
    // JS getUTCDay: 0=Sun, 1=Mon ... 6=Sat. Snap back to Monday.
    const dow = today.getUTCDay();
    const daysSinceMon = (dow + 6) % 7; // Mon=0, Tue=1, ... Sun=6
    const mon = new Date(today.getTime());
    mon.setUTCDate(mon.getUTCDate() - daysSinceMon);
    mon.setUTCHours(0, 0, 0, 0);
    const fri = new Date(mon.getTime());
    fri.setUTCDate(fri.getUTCDate() + 4); // Mon..Fri inclusive
    fri.setUTCHours(23, 59, 59, 999);
    return { mon, fri };
  }, [today]);

  // Issue computation — mirrors AdminView logic
  function clientIssues(c) {
    const status = (c.status || '').toUpperCase();
    const isClosedOrPending = status === 'CLOSED' || status === 'PENDING';
    const issues = [];
    if (!status) issues.push('Missing status');
    if (isClosedOrPending) {
      if (c.salesPrice == null || c.salesPrice === '' || c.salesPrice === 0) issues.push('Missing sales price');
      if (c.grossCommission == null || c.grossCommission === '' || c.grossCommission === 0) issues.push('Missing gross commission');
      const noSplits = !c.agentSplit && !c.partnerSplit && !c.teamSplit;
      if (noSplits) issues.push('No splits recorded');
      if (c.partner && String(c.partner).trim() && !c.partnerSplit) issues.push(`Partner listed (${c.partner}) but no partner split`);
    }
    if (status === 'CLOSED' && !c.closingDate) issues.push('Closed but no closing date');
    const yr = (s) => { const m = (s||'').match(/^(\d{4})/); return m ? +m[1] : null; };
    const cy = yr(c.contractDate); if (cy && (cy < 2020 || cy > 2030)) issues.push(`Suspicious contract date (${c.contractDate})`);
    const cl = yr(c.closingDate); if (cl && (cl < 2020 || cl > 2030)) issues.push(`Suspicious closing date (${c.closingDate})`);
    if (c.partner && /^\d/.test(String(c.partner).trim())) issues.push(`Partner field has a number (${c.partner})`);
    return issues;
  }

  const approaching = useMemoDB(() => {
    return clients
      .map(c => ({ ...c, _dtu: daysUntil(c.closingDate, today), _issues: clientIssues(c) }))
      .filter(c => {
        if (!c.closingDate) return false;
        const d = new Date(c.closingDate);
        if (isNaN(d)) return false;
        if (d < weekRange.mon || d > weekRange.fri) return false;
        const st = (c.status || '').toUpperCase();
        return st !== 'CLOSED' && st !== 'DFT';
      })
      .sort((a, b) => new Date(a.closingDate) - new Date(b.closingDate));
  }, [clients, today, weekRange]);

  function handleFixClick(c) {
    // Admin password gate (cached for the session)
    const ADMIN_PASS = localStorage.getItem('ct_admin_passcode') || '2026';
    const unlocked = sessionStorage.getItem('ct_admin_unlocked') === '1';
    if (!unlocked) {
      const entered = window.prompt('Enter admin passcode to fix this entry:');
      if (entered == null) return;
      if (entered !== ADMIN_PASS) {
        window.alert('Incorrect passcode.');
        return;
      }
      sessionStorage.setItem('ct_admin_unlocked', '1');
    }
    if (c._editKey) {
      localStorage.setItem('ct_open_fix', c._editKey);
    }
    location.hash = 'admin';
  }

  const totalClients = clients.length;
  const closedCount = stats.byStatus.CLOSED.count;
  const activeCount = stats.byStatus.ACTIVE.count;
  const pendingCount = stats.byStatus.PENDING.count;
  const totalTypeClosings = stats.byType.BUYER.count + stats.byType.SELLER.count + stats.byType.NEUTRAL.count;

  return (
    <div>
      <div className="page-head">
        <div>
          <h1 className="page-title">Team dashboard</h1>
        </div>
        <div style={{display:'flex', gap:8}}>
          <button className="btn">Export CSV</button>
          <button className="btn btn-primary">+ New client</button>
        </div>
      </div>

      {/* KPI row */}
      <div className="kpi-row">
        <div className="kpi">
          <div className="kpi-label">Closed volume</div>
          <div className="kpi-value">{fmtMoney(stats.totalVol)}</div>
          <div className="kpi-meta">{closedCount} closed YTD</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Pending volume</div>
          <div className="kpi-value">{fmtMoney(stats.pendingVol)}</div>
          <div className="kpi-meta">{pendingCount} pending</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Gross commission</div>
          <div className="kpi-value">{fmtMoney(stats.totalComm)}</div>
          <div className="kpi-meta" style={{display:'flex', flexDirection:'column', gap:2, marginTop:4}}>
            <span>Team split <strong style={{color:'var(--ink-2)'}}>{fmtMoney(stats.teamSplitTotal)}</strong></span>
            <span>Partner split <strong style={{color:'var(--ink-2)'}}>{fmtMoney(stats.partnerSplitTotal)}</strong></span>
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Avg sale price</div>
          <div className="kpi-value">{fmtMoney(stats.totalVol / (closedCount || 1))}</div>
          <div className="kpi-meta">Across {closedCount} closings</div>
        </div>
      </div>

      {/* Donut row: status + client type */}
      <div className="grid-2">
        <div className="card">
          <h3 className="card-title">Transactions by status</h3>
          <Donut
            centerLabel="Total"
            centerValue={stats.byStatus.ACTIVE.count + stats.byStatus.PENDING.count + stats.byStatus.CLOSED.count}
            segments={[
              { label: 'Active',  value: stats.byStatus.ACTIVE.count,  volume: stats.byStatus.ACTIVE.vol,  color: 'var(--active)' },
              { label: 'Pending', value: stats.byStatus.PENDING.count, volume: stats.byStatus.PENDING.vol, color: 'var(--pending)' },
              { label: 'Closed',  value: stats.byStatus.CLOSED.count,  volume: stats.byStatus.CLOSED.vol,  color: 'var(--closed)' },
            ]}
          />
        </div>
        <div className="card">
          <h3 className="card-title">Closings by client type</h3>
          <Donut
            centerLabel="Closed"
            centerValue={stats.byType.BUYER.count + stats.byType.SELLER.count + stats.byType.NEUTRAL.count}
            segments={[
              { label: 'Buyer',   value: stats.byType.BUYER.count,   volume: stats.byType.BUYER.vol,   color: '#3557a8' },
              { label: 'Seller',  value: stats.byType.SELLER.count,  volume: stats.byType.SELLER.vol,  color: '#c7823a' },
              { label: 'Neutral', value: stats.byType.NEUTRAL.count, volume: stats.byType.NEUTRAL.vol, color: '#6c7a89' },
            ]}
          />
        </div>
      </div>

      {/* Closing dates approaching — full width */}
      <div style={{marginBottom: 18}}>
      <div className="card">
        <div style={{display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:4}}>
          <h3 className="card-title" style={{marginBottom:0}}>Closing dates approaching</h3>
          <span style={{fontSize:11, color:'var(--ink-3)', letterSpacing:'0.08em', textTransform:'uppercase'}}>This week · Mon–Fri · {approaching.length}</span>
        </div>
        {approaching.length === 0 ? (
          <div style={{padding:'24px 8px', textAlign:'center', color:'var(--ink-3)', fontSize:13}}>
            No closings scheduled this week.
          </div>
        ) : (
          <table className="table">
            <thead>
              <tr>
                <th style={{width: 64}}>In</th>
                <th>Client</th>
                <th>Agent</th>
                <th>Date</th>
                <th className="num">Price</th>
                <th>Issues</th>
                <th style={{width: 70}}></th>
              </tr>
            </thead>
            <tbody>
              {approaching.map((c, i) => {
                const dtu = c._dtu;
                const urgent = dtu <= 3;
                const issues = c._issues || [];
                return (
                  <tr key={i}>
                    <td>
                      <span style={{
                        display:'inline-flex', alignItems:'baseline', gap:3,
                        fontFamily:'var(--font-mono)', fontSize:13,
                        color: urgent ? 'var(--dft)' : 'var(--ink-2)',
                        fontWeight: urgent ? 600 : 500
                      }}>
                        {dtu === 0 ? 'TODAY' : <>{dtu}<span style={{fontSize:10, color:'var(--ink-3)'}}>d</span></>}
                      </span>
                    </td>
                    <td>
                      <div style={{fontWeight:500}}>{c.client}</div>
                      <div style={{fontSize:11, color:'var(--ink-3)'}}>{c.type} · <span className={'pill ' + (c.status || '')} style={{padding:'1px 6px', fontSize:10}}><span className="dot"></span>{c.status}</span></div>
                    </td>
                    <td className="muted">{c.agent}</td>
                    <td className="muted" style={{fontFamily:'var(--font-mono)', fontSize:12}}>{fmtDate(c.closingDate)}</td>
                    <td className="num">{fmtMoney(c.salesPrice)}</td>
                    <td>
                      {issues.length === 0 ? (
                        <span style={{fontSize:11, color:'var(--ink-3)'}}>—</span>
                      ) : (
                        <ul style={{margin: 0, padding: '0 0 0 14px', color: 'var(--ink-2)', fontSize: 11, lineHeight: 1.4}}>
                          {issues.slice(0, 3).map((iss, j) => <li key={j}>{iss}</li>)}
                          {issues.length > 3 && <li style={{listStyle:'none', color:'var(--ink-3)'}}>+{issues.length - 3} more</li>}
                        </ul>
                      )}
                    </td>
                    <td>
                      {issues.length > 0 && (
                        <button className="btn btn-mini" onClick={() => handleFixClick(c)} title="Admin passcode required">
                          Fix
                        </button>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>
      </div>

      <div className="card" style={{marginBottom: 18}}>
        <h3 className="card-title">Monthly closings · 2026 vs 2025</h3>
        <p className="card-sub" style={{margin:'-6px 0 10px', fontSize:12, color:'var(--ink-3)', letterSpacing:'0.04em'}}>
          Volume (count) <span style={{margin:'0 8px'}}>·</span> 2025 shown below each month
        </p>
        <BarList rows={monthlyRows} format="money" subFormat="money" />
      </div>

      <div className="grid-2">
        <div className="card">
          <h3 className="card-title">Top lead sources</h3>
          <BarList rows={topSources} format="money" />
        </div>
        <div className="card">
          <h3 className="card-title">Sales volume by agent</h3>
          <p className="card-sub" style={{margin:'-6px 0 10px', fontSize:12, color:'var(--ink-3)', letterSpacing:'0.04em'}}>
            2026 YTD <span style={{margin:'0 8px'}}>·</span> Prior YTD shown below each bar
          </p>
          <BarList rows={topAgents} format="money" subFormat="money" />
        </div>
      </div>
    </div>
  );
}
window.Dashboard = Dashboard;
