import { useState, useEffect } from "react";

// ── Palette & design tokens ──────────────────────────────────────────────────
// Deep navy (#0F1B2D) ground, warm off-white (#F5F0E8) surface,
// gold accent (#C9A84C) for financial highlights, slate (#6B7A8D) for muted.
// Display: "Georgia" serif. Body/data: system-ui. Mono for $ figures.

const COLORS = {
  navy: "#0F1B2D",
  navyMid: "#1A2E47",
  gold: "#C9A84C",
  goldLight: "#F0DFA0",
  cream: "#F5F0E8",
  white: "#FFFFFF",
  slate: "#6B7A8D",
  slateLight: "#E8ECF0",
  red: "#C0392B",
  green: "#1A7A4A",
  greenLight: "#E8F5EE",
  redLight: "#FDECEA",
};

const css = `
  @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600;700&display=swap');

  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  body {
    font-family: system-ui, -apple-system, sans-serif;
    background: ${COLORS.navy};
    color: ${COLORS.navyMid};
    min-height: 100vh;
  }

  .app { display: flex; min-height: 100vh; }

  /* Sidebar */
  .sidebar {
    width: 220px; min-width: 220px;
    background: ${COLORS.navy};
    display: flex; flex-direction: column;
    padding: 0 0 24px 0;
    border-right: 1px solid rgba(201,168,76,0.15);
    position: sticky; top: 0; height: 100vh;
  }
  .sidebar-logo {
    padding: 28px 20px 20px;
    border-bottom: 1px solid rgba(201,168,76,0.2);
    margin-bottom: 12px;
  }
  .sidebar-logo h1 {
    font-family: 'Playfair Display', Georgia, serif;
    color: ${COLORS.gold};
    font-size: 1.2rem;
    line-height: 1.3;
    letter-spacing: 0.01em;
  }
  .sidebar-logo span {
    color: ${COLORS.slate};
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    display: block;
    margin-top: 2px;
  }
  .nav-item {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 20px;
    cursor: pointer;
    font-size: 0.88rem;
    color: rgba(245,240,232,0.6);
    border-left: 3px solid transparent;
    transition: all 0.15s;
    user-select: none;
  }
  .nav-item:hover { color: ${COLORS.cream}; background: rgba(255,255,255,0.04); }
  .nav-item.active {
    color: ${COLORS.gold};
    border-left-color: ${COLORS.gold};
    background: rgba(201,168,76,0.08);
    font-weight: 500;
  }
  .nav-icon { font-size: 1rem; width: 18px; text-align: center; }

  /* Main */
  .main {
    flex: 1;
    background: ${COLORS.cream};
    overflow-y: auto;
  }
  .page-header {
    background: ${COLORS.white};
    padding: 24px 32px 20px;
    border-bottom: 1px solid ${COLORS.slateLight};
    display: flex; align-items: center; justify-content: space-between;
  }
  .page-title {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.5rem;
    color: ${COLORS.navy};
  }
  .page-sub { font-size: 0.8rem; color: ${COLORS.slate}; margin-top: 2px; }
  .page-content { padding: 28px 32px; }

  /* Cards */
  .card {
    background: ${COLORS.white};
    border-radius: 8px;
    padding: 24px;
    border: 1px solid ${COLORS.slateLight};
  }
  .card-title {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: ${COLORS.slate};
    margin-bottom: 8px;
  }

  /* Stat grid */
  .stat-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 16px; margin-bottom: 28px; }
  .stat-card {
    background: ${COLORS.white};
    border-radius: 8px;
    padding: 20px 24px;
    border: 1px solid ${COLORS.slateLight};
    border-top: 3px solid transparent;
  }
  .stat-card.gold { border-top-color: ${COLORS.gold}; }
  .stat-card.green { border-top-color: ${COLORS.green}; }
  .stat-card.red { border-top-color: ${COLORS.red}; }
  .stat-card.navy { border-top-color: ${COLORS.navyMid}; }
  .stat-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: ${COLORS.slate}; }
  .stat-value { font-size: 1.7rem; font-weight: 700; color: ${COLORS.navy}; margin: 6px 0 2px; font-variant-numeric: tabular-nums; }
  .stat-sub { font-size: 0.75rem; color: ${COLORS.slate}; }

  /* Tables */
  .table-wrap { overflow-x: auto; }
  table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
  thead th {
    text-align: left;
    padding: 10px 14px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: ${COLORS.slate};
    background: ${COLORS.cream};
    border-bottom: 1px solid ${COLORS.slateLight};
    font-weight: 600;
  }
  tbody tr { border-bottom: 1px solid ${COLORS.slateLight}; transition: background 0.1s; }
  tbody tr:hover { background: #fafaf8; }
  tbody td { padding: 12px 14px; color: ${COLORS.navyMid}; }
  .mono { font-variant-numeric: tabular-nums; font-family: 'Courier New', monospace; }
  .income { color: ${COLORS.green}; font-weight: 600; }
  .expense { color: ${COLORS.red}; font-weight: 600; }

  /* Badge */
  .badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 99px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
  }
  .badge-green { background: ${COLORS.greenLight}; color: ${COLORS.green}; }
  .badge-red { background: ${COLORS.redLight}; color: ${COLORS.red}; }
  .badge-gold { background: #FEF8E6; color: #9A6F1A; }
  .badge-slate { background: ${COLORS.slateLight}; color: ${COLORS.slate}; }

  /* Buttons */
  .btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 9px 18px;
    border-radius: 6px;
    border: none; cursor: pointer;
    font-size: 0.85rem; font-weight: 500;
    transition: all 0.15s;
  }
  .btn-primary { background: ${COLORS.gold}; color: ${COLORS.navy}; }
  .btn-primary:hover { background: #b8942e; }
  .btn-outline {
    background: transparent;
    border: 1px solid ${COLORS.slateLight};
    color: ${COLORS.navyMid};
  }
  .btn-outline:hover { border-color: ${COLORS.slate}; }
  .btn-danger { background: ${COLORS.red}; color: white; }
  .btn-sm { padding: 5px 11px; font-size: 0.78rem; }

  .btn-delete {
    background: none; border: none; cursor: pointer;
    color: ${COLORS.slate}; font-size: 1.1rem; line-height: 1;
    padding: 2px 6px; border-radius: 4px; opacity: 0.5;
    transition: opacity 0.15s, color 0.15s;
  }
  .btn-delete:hover { opacity: 1; color: ${COLORS.red}; }

  /* Form */
  .form-row { display: grid; gap: 16px; margin-bottom: 16px; }
  .form-row.cols-2 { grid-template-columns: 1fr 1fr; }
  .form-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
  .form-group { display: flex; flex-direction: column; gap: 5px; }
  label { font-size: 0.78rem; font-weight: 600; color: ${COLORS.navy}; letter-spacing: 0.02em; }
  input, select, textarea {
    padding: 9px 12px;
    border: 1px solid ${COLORS.slateLight};
    border-radius: 6px;
    font-size: 0.875rem;
    color: ${COLORS.navyMid};
    background: ${COLORS.white};
    outline: none;
    transition: border-color 0.15s;
    font-family: inherit;
  }
  input:focus, select:focus, textarea:focus { border-color: ${COLORS.gold}; box-shadow: 0 0 0 3px rgba(201,168,76,0.12); }
  textarea { resize: vertical; min-height: 80px; }

  /* Modal */
  .modal-overlay {
    position: fixed; inset: 0;
    background: rgba(15,27,45,0.6);
    display: flex; align-items: center; justify-content: center;
    z-index: 100; padding: 20px;
    backdrop-filter: blur(2px);
  }
  .modal {
    background: ${COLORS.white};
    border-radius: 12px;
    width: 100%; max-width: 600px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 24px 60px rgba(0,0,0,0.25);
  }
  .modal-header {
    padding: 22px 28px 18px;
    border-bottom: 1px solid ${COLORS.slateLight};
    display: flex; justify-content: space-between; align-items: center;
  }
  .modal-header h2 {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.15rem; color: ${COLORS.navy};
  }
  .modal-body { padding: 24px 28px; }
  .modal-footer {
    padding: 16px 28px 22px;
    display: flex; justify-content: flex-end; gap: 10px;
    border-top: 1px solid ${COLORS.slateLight};
  }
  .close-btn {
    background: none; border: none; cursor: pointer;
    font-size: 1.3rem; color: ${COLORS.slate};
    line-height: 1; padding: 2px;
  }
  .close-btn:hover { color: ${COLORS.navy}; }

  /* Invoice preview */
  .invoice-preview {
    background: ${COLORS.white};
    border: 1px solid ${COLORS.slateLight};
    border-radius: 8px;
    padding: 32px;
    font-size: 0.875rem;
  }
  .invoice-top { display: flex; justify-content: space-between; margin-bottom: 28px; }
  .invoice-from h3 {
    font-family: 'Playfair Display', Georgia, serif;
    color: ${COLORS.navy}; font-size: 1.1rem; margin-bottom: 4px;
  }
  .invoice-from p, .invoice-to p { color: ${COLORS.slate}; font-size: 0.8rem; line-height: 1.7; }
  .invoice-meta { text-align: right; }
  .invoice-num { font-size: 1.5rem; font-weight: 700; color: ${COLORS.gold}; font-family: 'Playfair Display', Georgia, serif; }
  .invoice-lines { width: 100%; border-collapse: collapse; margin: 20px 0; }
  .invoice-lines th { background: ${COLORS.navy}; color: ${COLORS.gold}; padding: 8px 12px; text-align: left; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; }
  .invoice-lines td { padding: 10px 12px; border-bottom: 1px solid ${COLORS.slateLight}; }
  .invoice-total { text-align: right; }
  .invoice-total .total-line { display: flex; justify-content: flex-end; gap: 40px; margin-bottom: 6px; font-size: 0.85rem; color: ${COLORS.slate}; }
  .invoice-total .grand { color: ${COLORS.navy}; font-weight: 700; font-size: 1.1rem; }

  /* Lease card */
  .lease-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px,1fr)); gap: 16px; }
  .lease-card {
    background: ${COLORS.white};
    border-radius: 8px;
    border: 1px solid ${COLORS.slateLight};
    border-top: 4px solid ${COLORS.navy};
    padding: 20px;
  }
  .lease-card.expiring { border-top-color: ${COLORS.gold}; }
  .lease-card.expired { border-top-color: ${COLORS.red}; }
  .lease-card h3 { font-size: 1rem; font-weight: 600; color: ${COLORS.navy}; margin-bottom: 4px; }
  .lease-detail { font-size: 0.8rem; color: ${COLORS.slate}; line-height: 1.9; }
  .lease-detail strong { color: ${COLORS.navyMid}; font-weight: 600; }

  /* Divider */
  .divider { height: 1px; background: ${COLORS.slateLight}; margin: 24px 0; }

  /* Empty */
  .empty { text-align: center; padding: 48px 24px; color: ${COLORS.slate}; }
  .empty-icon { font-size: 2.5rem; margin-bottom: 12px; }
  .empty p { font-size: 0.875rem; }

  /* Tabs */
  .tabs { display: flex; gap: 4px; margin-bottom: 20px; background: ${COLORS.slateLight}; border-radius: 8px; padding: 4px; width: fit-content; }
  .tab { padding: 7px 16px; border-radius: 6px; border: none; cursor: pointer; font-size: 0.82rem; font-weight: 500; background: none; color: ${COLORS.slate}; transition: all 0.15s; }
  .tab.active { background: ${COLORS.white}; color: ${COLORS.navy}; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }

  @media (max-width: 900px) {
    .stat-grid { grid-template-columns: 1fr 1fr; }
    .sidebar { width: 60px; min-width: 60px; }
    .sidebar-logo, .nav-item span { display: none; }
    .nav-icon { margin: 0 auto; }
    .nav-item { justify-content: center; padding: 14px 0; }
  }
`;


// ── Helpers ──────────────────────────────────────────────────────────────────
const fmt = (n) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 0 }).format(n);
const today = () => new Date().toISOString().split("T")[0];
const daysUntil = (d) => Math.ceil((new Date(d) - new Date()) / 86400000);

const leaseStatus = (lease) => {
  const d = daysUntil(lease.end);
  if (d < 0) return "expired";
  if (d <= 60) return "expiring";
  return "active";
};

const nextInvoiceNum = (invoices) => {
  const max = invoices.reduce((m, i) => Math.max(m, parseInt(i.num.split("-")[1])), 0);
  return `INV-${String(max + 1).padStart(3, "0")}`;
};

// ── Components ───────────────────────────────────────────────────────────────

function Modal({ title, onClose, onSave, children, wide }) {
  return (
    <div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
      <div className="modal" style={wide ? { maxWidth: 740 } : {}}>
        <div className="modal-header">
          <h2>{title}</h2>
          <button className="close-btn" onClick={onClose}>×</button>
        </div>
        <div className="modal-body">{children}</div>
        {onSave && (
          <div className="modal-footer">
            <button className="btn btn-outline" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary" onClick={onSave}>Save</button>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Dashboard ────────────────────────────────────────────────────────────────
function Dashboard({ transactions, invoices, leases, tenants }) {
  const income = transactions.filter(t => t.type === "income").reduce((s, t) => s + t.amount, 0);
  const expenses = transactions.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0);
  const net = income - expenses;
  const pending = invoices.filter(i => i.status === "pending").reduce((s, i) => s + i.items.reduce((a, b) => a + b.rate * b.qty, 0), 0);
  const expiringLeases = leases.filter(l => leaseStatus(l) === "expiring" || leaseStatus(l) === "expired");

  const categories = {};
  transactions.filter(t => t.type === "expense").forEach(t => { categories[t.category] = (categories[t.category] || 0) + t.amount; });

  return (
    <div>
      <div className="stat-grid">
        <div className="stat-card green">
          <div className="stat-label">Total Income</div>
          <div className="stat-value" style={{ color: COLORS.green }}>{fmt(income)}</div>
          <div className="stat-sub">this period</div>
        </div>
        <div className="stat-card red">
          <div className="stat-label">Total Expenses</div>
          <div className="stat-value" style={{ color: COLORS.red }}>{fmt(expenses)}</div>
          <div className="stat-sub">this period</div>
        </div>
        <div className="stat-card gold">
          <div className="stat-label">Net Operating Income</div>
          <div className="stat-value" style={{ color: net >= 0 ? COLORS.green : COLORS.red }}>{fmt(net)}</div>
          <div className="stat-sub">income − expenses</div>
        </div>
        <div className="stat-card navy">
          <div className="stat-label">Pending Invoices</div>
          <div className="stat-value">{fmt(pending)}</div>
          <div className="stat-sub">{invoices.filter(i => i.status === "pending").length} invoice(s) outstanding</div>
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
        <div className="card">
          <div className="card-title">Recent Transactions</div>
          <div className="table-wrap">
            <table>
              <thead><tr><th>Date</th><th>Description</th><th>Amount</th></tr></thead>
              <tbody>
                {transactions.slice(-5).reverse().map(t => (
                  <tr key={t.id}>
                    <td style={{ color: COLORS.slate, fontSize: "0.8rem" }}>{t.date}</td>
                    <td>{t.description}</td>
                    <td className={`mono ${t.type}`}>{t.type === "income" ? "+" : "−"}{fmt(t.amount)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>

        <div className="card">
          <div className="card-title">Expense Breakdown</div>
          {Object.entries(categories).map(([cat, amt]) => (
            <div key={cat} style={{ marginBottom: 10 }}>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: "0.82rem", marginBottom: 4 }}>
                <span style={{ color: COLORS.navyMid }}>{cat}</span>
                <span className="mono" style={{ color: COLORS.slate }}>{fmt(amt)}</span>
              </div>
              <div style={{ height: 6, background: COLORS.slateLight, borderRadius: 99, overflow: "hidden" }}>
                <div style={{ height: "100%", width: `${(amt / expenses) * 100}%`, background: COLORS.gold, borderRadius: 99 }} />
              </div>
            </div>
          ))}
          {expiringLeases.length > 0 && (
            <>
              <div className="divider" />
              <div className="card-title">Lease Alerts</div>
              {expiringLeases.map(l => {
                const t = tenants.find(t => String(t.id) === String(l.tenantId));
                const d = daysUntil(l.end);
                return (
                  <div key={l.id} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8, fontSize: "0.83rem" }}>
                    <span>{t?.name} — {l.unit}</span>
                    <span className={`badge ${d < 0 ? "badge-red" : "badge-gold"}`}>
                      {d < 0 ? `Expired ${Math.abs(d)}d ago` : `Expires in ${d}d`}
                    </span>
                  </div>
                );
              })}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Transactions ─────────────────────────────────────────────────────────────
function Transactions({ transactions, onAddTransaction, onDeleteTransaction, tenants }) {
  const [showModal, setShowModal] = useState(false);
  const [tab, setTab] = useState("all");
  const [txPage, setTxPage] = useState(1);
  const [form, setForm] = useState({ date: today(), type: "income", category: "Rent", description: "", amount: "", tenantId: "" });

  const visible = tab === "all" ? transactions : transactions.filter(t => t.type === tab);
  const sorted = [...visible].sort((a, b) => b.date.localeCompare(a.date));
  const PAGE_SIZE = 20;
  const totalPages = Math.max(1, Math.ceil(sorted.length / PAGE_SIZE));
  const paginated = sorted.slice((txPage - 1) * PAGE_SIZE, txPage * PAGE_SIZE);

  const save = () => {
    if (!form.description || !form.amount) return;
    onAddTransaction({ ...form, amount: parseFloat(form.amount), tenantId: form.tenantId ? parseInt(form.tenantId) : null });
    setShowModal(false);
    setForm({ date: today(), type: "income", category: "Rent", description: "", amount: "", tenantId: "" });
  };

  const incCats = ["Rent", "Late Fee", "Security Deposit", "Parking", "Pet Fee", "Other Income"];
  const expCats = ["Repairs", "Maintenance", "Insurance", "Mortgage", "Taxes", "Utilities", "Management", "Landscaping", "Other Expense"];

  return (
    <div>
      <div className="tabs">
        {["all", "income", "expense"].map(t => (
          <button key={t} className={`tab ${tab === t ? "active" : ""}`} onClick={() => { setTab(t); setTxPage(1); }}>
            {t.charAt(0).toUpperCase() + t.slice(1)}
          </button>
        ))}
      </div>

      <div className="card">
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
          <div className="card-title" style={{ marginBottom: 0 }}>Transaction Ledger</div>
          <button className="btn btn-primary btn-sm" onClick={() => setShowModal(true)}>＋ Add Transaction</button>
        </div>
        <div className="table-wrap">
          <table>
            <thead>
              <tr><th>Date</th><th>Type</th><th>Category</th><th>Description</th><th>Tenant</th><th style={{ textAlign: "right" }}>Amount</th><th /></tr>
            </thead>
            <tbody>
              {visible.length === 0 && (
                <tr><td colSpan={7}><div className="empty"><div className="empty-icon">📋</div><p>No transactions yet</p></div></td></tr>
              )}
              {paginated.map(t => {
                const tenant = tenants.find(tn => String(tn.id) === String(t.tenantId));
                return (
                  <tr key={t.id}>
                    <td style={{ color: COLORS.slate, fontSize: "0.8rem" }}>{t.date}</td>
                    <td><span className={`badge ${t.type === "income" ? "badge-green" : "badge-red"}`}>{t.type}</span></td>
                    <td style={{ color: COLORS.slate }}>{t.category}</td>
                    <td>{t.description}</td>
                    <td style={{ color: COLORS.slate }}>{tenant?.name || "—"}</td>
                    <td className={`mono ${t.type}`} style={{ textAlign: "right" }}>
                      {t.type === "income" ? "+" : "−"}{fmt(t.amount)}
                    </td>
                    <td><button className="btn-delete" onClick={() => onDeleteTransaction(t.id)} title="Delete">×</button></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        {totalPages > 1 && (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 16, fontSize: "0.82rem", color: COLORS.slate }}>
            <span>{sorted.length} transactions · page {txPage} of {totalPages}</span>
            <div style={{ display: "flex", gap: 6 }}>
              <button className="btn btn-outline btn-sm" disabled={txPage === 1} onClick={() => setTxPage(p => p - 1)} style={{ opacity: txPage === 1 ? 0.4 : 1 }}>← Prev</button>
              {Array.from({ length: totalPages }, (_, i) => i + 1).map(n => (
                <button key={n} className="btn btn-sm" onClick={() => setTxPage(n)}
                  style={{ background: n === txPage ? COLORS.gold : COLORS.slateLight, color: n === txPage ? COLORS.navy : COLORS.slate, border: "none", cursor: "pointer", borderRadius: 6, padding: "5px 10px", fontWeight: n === txPage ? 600 : 400 }}>
                  {n}
                </button>
              ))}
              <button className="btn btn-outline btn-sm" disabled={txPage === totalPages} onClick={() => setTxPage(p => p + 1)} style={{ opacity: txPage === totalPages ? 0.4 : 1 }}>Next →</button>
            </div>
          </div>
        )}
      </div>

      {showModal && (
        <Modal title="Add Transaction" onClose={() => setShowModal(false)} onSave={save}>
          <div className="form-row cols-2">
            <div className="form-group"><label>Date</label><input type="date" value={form.date} onChange={e => setForm(p => ({ ...p, date: e.target.value }))} /></div>
            <div className="form-group">
              <label>Type</label>
              <select value={form.type} onChange={e => setForm(p => ({ ...p, type: e.target.value, category: e.target.value === "income" ? "Rent" : "Repairs" }))}>
                <option value="income">Income</option>
                <option value="expense">Expense</option>
              </select>
            </div>
          </div>
          <div className="form-row cols-2">
            <div className="form-group">
              <label>Category</label>
              <select value={form.category} onChange={e => setForm(p => ({ ...p, category: e.target.value }))}>
                {(form.type === "income" ? incCats : expCats).map(c => <option key={c}>{c}</option>)}
              </select>
            </div>
            <div className="form-group">
              <label>Tenant (optional)</label>
              <select value={form.tenantId} onChange={e => setForm(p => ({ ...p, tenantId: e.target.value }))}>
                <option value="">— None —</option>
                {tenants.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}
              </select>
            </div>
          </div>
          <div className="form-row">
            <div className="form-group"><label>Description</label><input placeholder="e.g. June rent — Unit 1A" value={form.description} onChange={e => setForm(p => ({ ...p, description: e.target.value }))} /></div>
          </div>
          <div className="form-row">
            <div className="form-group"><label>Amount ($)</label><input type="number" placeholder="0.00" value={form.amount} onChange={e => setForm(p => ({ ...p, amount: e.target.value }))} /></div>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Invoices ─────────────────────────────────────────────────────────────────
function InvoiceLineItem({ item, idx, onChange, onRemove }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr 60px 100px 32px", gap: 8, marginBottom: 8, alignItems: "center" }}>
      <input placeholder="Description" value={item.desc} onChange={e => onChange(idx, "desc", e.target.value)} />
      <input type="number" placeholder="Qty" value={item.qty} onChange={e => onChange(idx, "qty", parseFloat(e.target.value) || 1)} style={{ textAlign: "center" }} />
      <input type="number" placeholder="Rate" value={item.rate} onChange={e => onChange(idx, "rate", parseFloat(e.target.value) || 0)} />
      <button className="btn btn-sm" style={{ background: COLORS.slateLight, border: "none", cursor: "pointer", color: COLORS.red, borderRadius: 6 }} onClick={() => onRemove(idx)}>×</button>
    </div>
  );
}

function InvoicePreview({ inv, tenants, fromName }) {
  const tenant = tenants.find(t => String(t.id) === String(inv.tenantId));
  const subtotal = inv.items.reduce((s, i) => s + i.qty * i.rate, 0);
  return (
    <div className="invoice-preview">
      <div className="invoice-top">
        <div className="invoice-from">
          <h3>{fromName || "Kenji Morishige"}</h3>
          <p>Tax ID: 99-4686386<br />kenji@kenjim.com<br />408.813.3323</p>
        </div>
        <div className="invoice-meta">
          <div className="invoice-num">{inv.num || "INV-XXX"}</div>
          <p style={{ color: COLORS.slate, fontSize: "0.8rem", marginTop: 4 }}>
            Issue date: {inv.date}<br />Due date: {inv.due}
          </p>
        </div>
      </div>
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.08em", color: COLORS.slate, marginBottom: 4 }}>Bill To</div>
        <strong style={{ color: COLORS.navy }}>{tenant?.name || "—"}</strong>
        <p style={{ color: COLORS.slate, fontSize: "0.8rem" }}>{tenant?.unit}<br />{tenant?.email}</p>
      </div>
      <table className="invoice-lines">
        <thead><tr><th>Description</th><th style={{ textAlign: "center" }}>Qty</th><th style={{ textAlign: "right" }}>Rate</th><th style={{ textAlign: "right" }}>Total</th></tr></thead>
        <tbody>
          {inv.items.map((item, i) => (
            <tr key={i}>
              <td>{item.desc}</td>
              <td style={{ textAlign: "center" }}>{item.qty}</td>
              <td style={{ textAlign: "right" }} className="mono">{fmt(item.rate)}</td>
              <td style={{ textAlign: "right" }} className="mono">{fmt(item.qty * item.rate)}</td>
            </tr>
          ))}
        </tbody>
      </table>
      <div className="invoice-total">
        <div className="total-line"><span>Subtotal</span><span className="mono">{fmt(subtotal)}</span></div>
        <div className="total-line grand"><span>Total Due</span><span className="mono">{fmt(subtotal)}</span></div>
      </div>
      <div style={{ marginTop: 24, paddingTop: 16, borderTop: `1px solid ${COLORS.slateLight}`, fontSize: "0.75rem", color: COLORS.slate }}>
        Please pay by {inv.due}. Questions? Contact kenji@kenjim.com or 408.813.3323.
      </div>
    </div>
  );
}

function Invoices({ invoices, onAddInvoice, onUpdateInvoice, onDeleteInvoice, tenants, leases }) {
  const [showNew, setShowNew] = useState(false);
  const [viewing, setViewing] = useState(null);
  const [form, setForm] = useState({ tenantId: "", date: today(), due: "", items: [{ desc: "", qty: 1, rate: 0 }], status: "pending" });

  const updateItem = (idx, key, val) => setForm(p => { const items = [...p.items]; items[idx] = { ...items[idx], [key]: val }; return { ...p, items }; });
  const addItem = () => setForm(p => ({ ...p, items: [...p.items, { desc: "", qty: 1, rate: 0 }] }));
  const removeItem = (idx) => setForm(p => ({ ...p, items: p.items.filter((_, i) => i !== idx) }));

  const save = () => {
    if (!form.tenantId || form.items.length === 0) return;
    const newInv = { ...form, num: nextInvoiceNum(invoices), tenantId: parseInt(form.tenantId) };
    onAddInvoice(newInv);
    setShowNew(false);
    setForm({ tenantId: "", date: today(), due: "", items: [{ desc: "", qty: 1, rate: 0 }], status: "pending" });
  };

  const markPaid = (id) => onUpdateInvoice(id, { status: "paid" });

  const generateMonthly = () => {
    const activeLease = leases.find(l => leaseStatus(l) === "active" || leaseStatus(l) === "expiring");
    if (!activeLease) { alert("No active lease found."); return; }
    const tenant = tenants.find(t => String(t.id) === String(activeLease.tenantId));
    if (!tenant) { alert("Lease tenant not found."); return; }

    // Find the latest invoice month to determine next month
    const tenantInvoices = invoices.filter(i => String(i.tenantId) === String(activeLease.tenantId));
    let nextMonth;
    if (tenantInvoices.length > 0) {
      const lastDate = tenantInvoices.map(i => i.date).sort().reverse()[0];
      const d = new Date(lastDate + "T00:00:00");
      d.setMonth(d.getMonth() + 1);
      nextMonth = d;
    } else {
      nextMonth = new Date();
      nextMonth.setDate(1);
    }

    const monthName = nextMonth.toLocaleString("en-US", { month: "long", year: "numeric" });
    const issueDate = nextMonth.toISOString().split("T")[0];
    const dueDate = new Date(nextMonth);
    dueDate.setDate(5);
    const dueDateStr = dueDate.toISOString().split("T")[0];

    const newInv = {
      num: nextInvoiceNum(invoices),
      tenantId: activeLease.tenantId,
      date: issueDate,
      due: dueDateStr,
      status: "pending",
      items: [{ desc: `Monthly Rent — ${monthName}`, qty: 1, rate: activeLease.rent }],
    };
    onAddInvoice(newInv);
  };

  const sendInvoiceEmail = (inv) => {
    const tenant = tenants.find(t => String(t.id) === String(inv.tenantId));
    if (!tenant?.email) { alert("No email address on file for this tenant."); return; }
    const total = inv.items.reduce((s, i) => s + i.qty * i.rate, 0);
    const lineItems = inv.items.map(i =>
      `  ${i.desc.padEnd(40)} ${fmt(i.qty * i.rate).padStart(10)}`
    ).join("\n");
    const subject = encodeURIComponent(`Invoice ${inv.num} — Due ${inv.due}`);
    const body = encodeURIComponent(
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  INVOICE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

From:   Kenji Morishige
        Tax ID: 99-4686386
        kenji@kenjim.com  |  408.813.3323

To:     ${tenant.name}
        ${tenant.unit}
        ${tenant.email}

──────────────────────────────────────────
  Invoice #:    ${inv.num}
  Issue Date:   ${inv.date}
  Due Date:     ${inv.due}
──────────────────────────────────────────

  CHARGES

${lineItems}

──────────────────────────────────────────
  TOTAL DUE     ${fmt(total).padStart(10)}
──────────────────────────────────────────

Please remit payment by ${inv.due}.
Questions? Reply to this email or call 408.813.3323.

Thank you,
Kenji Morishige`
    );
    window.open(`mailto:${tenant.email}?cc=kenji@kenjim.com&subject=${subject}&body=${body}`);
  };

  const sendPaymentEmail = (inv) => {
    const tenant = tenants.find(t => String(t.id) === String(inv.tenantId));
    if (!tenant?.email) { alert("No email address on file for this tenant."); return; }
    const total = inv.items.reduce((s, i) => s + i.qty * i.rate, 0);
    const subject = encodeURIComponent(`Payment Received — ${inv.num}`);
    const body = encodeURIComponent(
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  PAYMENT CONFIRMATION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Hi ${tenant.name},

This is to confirm that your payment has been received and applied to the following invoice.

──────────────────────────────────────────
  Invoice #:    ${inv.num}
  Property:     ${tenant.unit}
  Amount Paid:  ${fmt(total)}
  Date Paid:    ${today()}
  Status:       PAID IN FULL ✓
──────────────────────────────────────────

Your account is up to date for this invoice. Thank you for your payment!

If you have any questions, please contact:
  kenji@kenjim.com  |  408.813.3323

Thank you,
Kenji Morishige`
    );
    window.open(`mailto:${tenant.email}?cc=kenji@kenjim.com&subject=${subject}&body=${body}`);
  };

  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}>
        <button className="btn btn-outline" onClick={generateMonthly}>⟳ Generate Monthly Invoice</button>
        <button className="btn btn-primary" onClick={() => setShowNew(true)}>＋ Create Invoice</button>
      </div>

      <div className="card">
        <div className="table-wrap">
          <table>
            <thead>
              <tr><th>Invoice #</th><th>Tenant</th><th>Issue Date</th><th>Due Date</th><th>Amount</th><th>Status</th><th>Actions</th></tr>
            </thead>
            <tbody>
              {invoices.length === 0 && (
                <tr><td colSpan={7}><div className="empty"><div className="empty-icon">🧾</div><p>No invoices yet</p></div></td></tr>
              )}
              {[...invoices].reverse().map(inv => {
                const tenant = tenants.find(t => String(t.id) === String(inv.tenantId));
                const total = inv.items.reduce((s, i) => s + i.qty * i.rate, 0);
                return (
                  <tr key={inv.id}>
                    <td style={{ fontWeight: 600, color: COLORS.gold }}>{inv.num}</td>
                    <td>{tenant?.name}</td>
                    <td style={{ color: COLORS.slate }}>{inv.date}</td>
                    <td style={{ color: COLORS.slate }}>{inv.due}</td>
                    <td className="mono">{fmt(total)}</td>
                    <td><span className={`badge ${inv.status === "paid" ? "badge-green" : "badge-gold"}`}>{inv.status}</span></td>
                    <td style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                      <button className="btn btn-outline btn-sm" onClick={() => setViewing(inv)}>View</button>
                      <button className="btn btn-sm" style={{ background: COLORS.slateLight, color: COLORS.navyMid, border: "none", cursor: "pointer", borderRadius: 6, padding: "5px 10px", fontSize: "0.78rem" }} onClick={() => sendInvoiceEmail(inv)}>✉ Invoice</button>
                      <button className="btn btn-sm" style={{ background: "#E8F0FD", color: "#2255CC", border: "none", cursor: "pointer", borderRadius: 6, padding: "5px 10px", fontSize: "0.78rem" }} onClick={() => sendPaymentEmail(inv)}>✉ Payment Rcvd</button>
                      {inv.status === "pending" && (
                        <button className="btn btn-sm" style={{ background: COLORS.greenLight, color: COLORS.green, border: "none", cursor: "pointer", borderRadius: 6, padding: "5px 10px", fontSize: "0.78rem" }} onClick={() => markPaid(inv.id)}>Mark Paid</button>
                      )}
                      <button className="btn-delete" onClick={() => onDeleteInvoice(inv.id)} title="Delete">×</button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {showNew && (
        <Modal title="Create Invoice" onClose={() => setShowNew(false)} onSave={save} wide>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
            <div>
              <div className="form-row">
                <div className="form-group">
                  <label>Tenant</label>
                  <select value={form.tenantId} onChange={e => setForm(p => ({ ...p, tenantId: e.target.value }))}>
                    <option value="">Select tenant...</option>
                    {tenants.map(t => <option key={t.id} value={t.id}>{t.name} — {t.unit}</option>)}
                  </select>
                </div>
              </div>
              <div className="form-row cols-2">
                <div className="form-group"><label>Issue Date</label><input type="date" value={form.date} onChange={e => setForm(p => ({ ...p, date: e.target.value }))} /></div>
                <div className="form-group"><label>Due Date</label><input type="date" value={form.due} onChange={e => setForm(p => ({ ...p, due: e.target.value }))} /></div>
              </div>
              <div style={{ marginBottom: 8 }}>
                <div style={{ display: "grid", gridTemplateColumns: "1fr 60px 100px 32px", gap: 8, marginBottom: 6 }}>
                  <span style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.06em", color: COLORS.slate }}>Description</span>
                  <span style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.06em", color: COLORS.slate, textAlign: "center" }}>Qty</span>
                  <span style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.06em", color: COLORS.slate }}>Rate ($)</span>
                  <span />
                </div>
                {form.items.map((item, idx) => (
                  <InvoiceLineItem key={idx} item={item} idx={idx} onChange={updateItem} onRemove={removeItem} />
                ))}
                <button className="btn btn-outline btn-sm" onClick={addItem} style={{ marginTop: 6 }}>＋ Add line</button>
              </div>
            </div>
            <div>
              <div style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.08em", color: COLORS.slate, marginBottom: 10 }}>Preview</div>
              <InvoicePreview inv={{ ...form, num: nextInvoiceNum(invoices) }} tenants={tenants} />
            </div>
          </div>
        </Modal>
      )}

      {viewing && (
        <Modal title={`Invoice ${viewing.num}`} onClose={() => setViewing(null)}>
          <InvoicePreview inv={viewing} tenants={tenants} />
        </Modal>
      )}
    </div>
  );
}

// ── Leases ───────────────────────────────────────────────────────────────────
function Leases({ leases, onAddLease, onDeleteLease, tenants }) {
  const [showModal, setShowModal] = useState(false);
  const [form, setForm] = useState({ tenantId: "", unit: "", rent: "", deposit: "", start: today(), end: "" });

  const save = () => {
    if (!form.tenantId || !form.unit || !form.rent) return;
    onAddLease({ ...form, tenantId: parseInt(form.tenantId), rent: parseFloat(form.rent), deposit: parseFloat(form.deposit || 0), status: "active" });
    setShowModal(false);
    setForm({ tenantId: "", unit: "", rent: "", deposit: "", start: today(), end: "" });
  };

  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}>
        <div />
        <button className="btn btn-primary" onClick={() => setShowModal(true)}>＋ Add Lease</button>
      </div>

      <div className="lease-grid">
        {leases.length === 0 && (
          <div className="empty"><div className="empty-icon">📄</div><p>No leases yet</p></div>
        )}
        {leases.map(lease => {
          const tenant = tenants.find(t => String(t.id) === String(lease.tenantId));
          const st = leaseStatus(lease);
          const d = daysUntil(lease.end);
          return (
            <div key={lease.id} className={`lease-card ${st === "active" ? "" : st}`}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 12 }}>
                <div>
                  <h3>{tenant?.name || "Unknown Tenant"}</h3>
                  <div style={{ color: COLORS.slate, fontSize: "0.82rem" }}>{lease.unit}</div>
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <span className={`badge ${st === "active" ? "badge-green" : st === "expiring" ? "badge-gold" : "badge-red"}`}>
                    {st === "active" ? "Active" : st === "expiring" ? `Expires in ${d}d` : "Expired"}
                  </span>
                  <button className="btn-delete" onClick={() => onDeleteLease(lease.id)} title="Delete">×</button>
                </div>
              </div>
              <div className="lease-detail">
                <div><strong>Monthly Rent:</strong> {fmt(lease.rent)}</div>
                <div><strong>Security Deposit:</strong> {fmt(lease.deposit)}</div>
                <div><strong>Lease Start:</strong> {lease.start}</div>
                <div><strong>Lease End:</strong> {lease.end}</div>
                {tenant && <><div><strong>Email:</strong> {tenant.email}</div><div><strong>Phone:</strong> {tenant.phone}</div></>}
              </div>
            </div>
          );
        })}
      </div>

      {showModal && (
        <Modal title="Add Lease" onClose={() => setShowModal(false)} onSave={save}>
          <div className="form-row">
            <div className="form-group">
              <label>Tenant</label>
              <select value={form.tenantId} onChange={e => {
                const t = tenants.find(t => t.id === parseInt(e.target.value));
                setForm(p => ({ ...p, tenantId: e.target.value, unit: t?.unit || p.unit }));
              }}>
                <option value="">Select tenant...</option>
                {tenants.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}
              </select>
            </div>
          </div>
          <div className="form-row cols-2">
            <div className="form-group"><label>Unit</label><input placeholder="e.g. Unit 1A" value={form.unit} onChange={e => setForm(p => ({ ...p, unit: e.target.value }))} /></div>
            <div className="form-group"><label>Monthly Rent ($)</label><input type="number" placeholder="0.00" value={form.rent} onChange={e => setForm(p => ({ ...p, rent: e.target.value }))} /></div>
          </div>
          <div className="form-row cols-2">
            <div className="form-group"><label>Security Deposit ($)</label><input type="number" placeholder="0.00" value={form.deposit} onChange={e => setForm(p => ({ ...p, deposit: e.target.value }))} /></div>
            <div className="form-group" />
          </div>
          <div className="form-row cols-2">
            <div className="form-group"><label>Start Date</label><input type="date" value={form.start} onChange={e => setForm(p => ({ ...p, start: e.target.value }))} /></div>
            <div className="form-group"><label>End Date</label><input type="date" value={form.end} onChange={e => setForm(p => ({ ...p, end: e.target.value }))} /></div>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Tenants ──────────────────────────────────────────────────────────────────
function EditableCell({ value, onSave, type = "text" }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);

  const commit = () => {
    setEditing(false);
    if (draft !== value) onSave(draft);
  };

  if (editing) {
    return (
      <input
        autoFocus
        type={type}
        value={draft}
        onChange={e => setDraft(e.target.value)}
        onBlur={commit}
        onKeyDown={e => { if (e.key === "Enter") commit(); if (e.key === "Escape") { setDraft(value); setEditing(false); } }}
        style={{ width: "100%", padding: "3px 6px", fontSize: "inherit", border: `1px solid ${COLORS.gold}`, borderRadius: 4, outline: "none" }}
      />
    );
  }

  return (
    <span
      onClick={() => { setDraft(value); setEditing(true); }}
      title="Click to edit"
      style={{ cursor: "text", color: COLORS.slate, borderBottom: `1px dashed ${COLORS.slateLight}`, paddingBottom: 1 }}
    >
      {value || <span style={{ opacity: 0.4 }}>—</span>}
    </span>
  );
}

function Tenants({ tenants, onAddTenant, onUpdateTenant, onDeleteTenant }) {
  const [showModal, setShowModal] = useState(false);
  const [form, setForm] = useState({ name: "", unit: "", email: "", phone: "" });

  const save = () => {
    if (!form.name || !form.unit) return;
    onAddTenant(form);
    setShowModal(false);
    setForm({ name: "", unit: "", email: "", phone: "" });
  };

  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}>
        <div />
        <button className="btn btn-primary" onClick={() => setShowModal(true)}>＋ Add Tenant</button>
      </div>
      <div className="card">
        <div className="table-wrap">
          <table>
            <thead><tr><th>Name</th><th>Unit</th><th>Email</th><th>Phone</th><th /></tr></thead>
            <tbody>
              {tenants.length === 0 && (
                <tr><td colSpan={5}><div className="empty"><div className="empty-icon">👤</div><p>No tenants yet</p></div></td></tr>
              )}
              {tenants.map(t => (
                <tr key={t.id}>
                  <td style={{ fontWeight: 500 }}>{t.name}</td>
                  <td><span className="badge badge-slate">{t.unit}</span></td>
                  <td><EditableCell value={t.email} type="email" onSave={val => onUpdateTenant(t.id, { email: val })} /></td>
                  <td><EditableCell value={t.phone} onSave={val => onUpdateTenant(t.id, { phone: val })} /></td>
                  <td><button className="btn-delete" onClick={() => onDeleteTenant(t.id)} title="Delete">×</button></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      {showModal && (
        <Modal title="Add Tenant" onClose={() => setShowModal(false)} onSave={save}>
          <div className="form-row cols-2">
            <div className="form-group"><label>Full Name</label><input placeholder="Jane Doe" value={form.name} onChange={e => setForm(p => ({ ...p, name: e.target.value }))} /></div>
            <div className="form-group"><label>Unit</label><input placeholder="Unit 1A" value={form.unit} onChange={e => setForm(p => ({ ...p, unit: e.target.value }))} /></div>
          </div>
          <div className="form-row cols-2">
            <div className="form-group"><label>Email</label><input type="email" placeholder="tenant@email.com" value={form.email} onChange={e => setForm(p => ({ ...p, email: e.target.value }))} /></div>
            <div className="form-group"><label>Phone</label><input placeholder="212-555-0100" value={form.phone} onChange={e => setForm(p => ({ ...p, phone: e.target.value }))} /></div>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Property P&L ─────────────────────────────────────────────────────────────
function PropertyView({ property, transactions, leases, invoices, tenants }) {
  const [yearFilter, setYearFilter] = useState("all");

  const propTx = transactions.filter(t => String(t.propertyId) === String(property.id));
  const years = [...new Set(propTx.map(t => t.date.slice(0, 4)))].sort().reverse();

  const filtered = yearFilter === "all" ? propTx : propTx.filter(t => t.date.startsWith(yearFilter));
  const income   = filtered.filter(t => t.type === "income").reduce((s, t) => s + t.amount, 0);
  const expenses = filtered.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0);
  const noi      = income - expenses;

  // Expenses by category
  const byCategory = filtered
    .filter(t => t.type === "expense")
    .reduce((acc, t) => { acc[t.category] = (acc[t.category] || 0) + t.amount; return acc; }, {});
  const catEntries = Object.entries(byCategory).sort((a, b) => b[1] - a[1]);
  const maxCat = catEntries[0]?.[1] || 1;

  const activeLease = leases.find(l => String(l.propertyId) === String(property.id) && (leaseStatus(l) === "active" || leaseStatus(l) === "expiring"));
  const tenant = activeLease ? tenants.find(t => String(t.id) === String(activeLease.tenantId)) : null;
  const pendingInvoices = invoices.filter(i => String(i.propertyId) === String(property.id) && i.status === "pending");
  const pendingTotal = pendingInvoices.reduce((s, i) => s + i.items.reduce((ss, li) => ss + li.qty * li.rate, 0), 0);

  return (
    <div>
      {/* Property Card */}
      <div className="card" style={{ marginBottom: 20 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
          <div>
            <div style={{ fontFamily: "'Playfair Display', Georgia, serif", fontSize: "1.1rem", fontWeight: 600, color: COLORS.navy, marginBottom: 4 }}>
              {property.address}
            </div>
            <div style={{ color: COLORS.slate, fontSize: "0.85rem" }}>{property.city}, {property.state} {property.zip} &nbsp;·&nbsp; {property.type} &nbsp;·&nbsp; Since {property.purchaseYear}</div>
          </div>
          <div style={{ textAlign: "right" }}>
            {tenant ? (
              <>
                <div style={{ fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.08em", color: COLORS.slate }}>Current Tenant</div>
                <div style={{ fontWeight: 500, color: COLORS.navy }}>{tenant.name}</div>
                <div style={{ fontSize: "0.8rem", color: COLORS.slate }}>{fmt(activeLease.rent)}/mo · Ends {activeLease.end}</div>
              </>
            ) : <span className="badge badge-red">Vacant</span>}
          </div>
        </div>
        {pendingTotal > 0 && (
          <div style={{ marginTop: 12, padding: "8px 12px", background: COLORS.redLight, borderRadius: 6, fontSize: "0.82rem", color: COLORS.red }}>
            Outstanding balance: <strong>{fmt(pendingTotal)}</strong> across {pendingInvoices.length} pending invoice{pendingInvoices.length !== 1 ? "s" : ""}
          </div>
        )}
      </div>

      {/* Year filter + P&L stats */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
        <div className="tabs">
          <button className={`tab ${yearFilter === "all" ? "active" : ""}`} onClick={() => setYearFilter("all")}>All Years</button>
          {years.map(y => <button key={y} className={`tab ${yearFilter === y ? "active" : ""}`} onClick={() => setYearFilter(y)}>{y}</button>)}
        </div>
      </div>

      <div className="stat-grid" style={{ marginBottom: 20 }}>
        <div className="stat-card"><div className="stat-label">Total Income</div><div className="stat-value" style={{ color: COLORS.green }}>{fmt(income)}</div></div>
        <div className="stat-card"><div className="stat-label">Total Expenses</div><div className="stat-value" style={{ color: COLORS.red }}>{fmt(expenses)}</div></div>
        <div className="stat-card"><div className="stat-label">Net Operating Income</div><div className="stat-value" style={{ color: noi >= 0 ? COLORS.green : COLORS.red }}>{fmt(noi)}</div></div>
        <div className="stat-card"><div className="stat-label">Transactions</div><div className="stat-value">{filtered.length}</div></div>
      </div>

      {/* Expense breakdown */}
      {catEntries.length > 0 && (
        <div className="card" style={{ marginBottom: 20 }}>
          <div className="card-title">Expense Breakdown</div>
          {catEntries.map(([cat, amt]) => (
            <div key={cat} style={{ marginBottom: 10 }}>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: "0.82rem", marginBottom: 4 }}>
                <span>{cat}</span><span className="mono">{fmt(amt)}</span>
              </div>
              <div style={{ height: 6, background: COLORS.slateLight, borderRadius: 3 }}>
                <div style={{ height: 6, borderRadius: 3, background: COLORS.gold, width: `${(amt / maxCat) * 100}%` }} />
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Transaction list */}
      <div className="card">
        <div className="card-title">Transaction History</div>
        <div className="table-wrap">
          <table>
            <thead><tr><th>Date</th><th>Type</th><th>Category</th><th>Description</th><th style={{ textAlign: "right" }}>Amount</th></tr></thead>
            <tbody>
              {filtered.length === 0 && <tr><td colSpan={5}><div className="empty"><p>No transactions for this period</p></div></td></tr>}
              {[...filtered].sort((a, b) => b.date.localeCompare(a.date)).map(t => (
                <tr key={t.id}>
                  <td style={{ color: COLORS.slate, fontSize: "0.8rem" }}>{t.date}</td>
                  <td><span className={`badge ${t.type === "income" ? "badge-green" : "badge-red"}`}>{t.type}</span></td>
                  <td style={{ color: COLORS.slate }}>{t.category}</td>
                  <td style={{ fontSize: "0.82rem" }}>{t.description}</td>
                  <td className={`mono ${t.type}`} style={{ textAlign: "right" }}>{t.type === "income" ? "+" : "−"}{fmt(t.amount)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ── App Shell ────────────────────────────────────────────────────────────────
const NAV = [
  { id: "dashboard", icon: "📊", label: "Dashboard" },
  { id: "properties", icon: "🏠", label: "Properties" },
  { id: "transactions", icon: "💳", label: "Transactions" },
  { id: "invoices", icon: "🧾", label: "Invoices" },
  { id: "leases", icon: "📄", label: "Leases" },
  { id: "tenants", icon: "👤", label: "Tenants" },
];

const api = {
  getAll: (resource) => fetch(`/${resource}`).then(r => r.json()),
  post: (resource, body) => fetch(`/${resource}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }).then(r => r.json()),
  patch: (resource, id, body) => fetch(`/${resource}/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }).then(r => r.json()),
  delete: (resource, id) => fetch(`/${resource}/${id}`, { method: "DELETE" }),
};

export default function App() {
  const [page, setPage] = useState("dashboard");
  const [properties, setProperties] = useState([]);
  const [tenants, setTenants] = useState([]);
  const [leases, setLeases] = useState([]);
  const [transactions, setTransactions] = useState([]);
  const [invoices, setInvoices] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    Promise.all([
      api.getAll("properties"),
      api.getAll("tenants"),
      api.getAll("leases"),
      api.getAll("transactions"),
      api.getAll("invoices"),
    ]).then(([props, t, l, tr, inv]) => {
      setProperties(props);
      setTenants(t);
      setLeases(l);
      setTransactions(tr);
      setInvoices(inv);
      setLoading(false);
    });
  }, []);

  const onAddTenant = (data) =>
    api.post("tenants", data).then(t => setTenants(prev => [...prev, t]));

  const onAddLease = (data) =>
    api.post("leases", data).then(l => setLeases(prev => [...prev, l]));

  const onAddTransaction = (data) =>
    api.post("transactions", data).then(t => setTransactions(prev => [...prev, t]));

  const onAddInvoice = (data) =>
    api.post("invoices", data).then(inv => setInvoices(prev => [...prev, inv]));

  const onUpdateInvoice = (id, changes) =>
    api.patch("invoices", id, changes).then(updated => setInvoices(prev => prev.map(i => i.id === id ? updated : i)));

  const onUpdateTenant = (id, changes) =>
    api.patch("tenants", id, changes).then(updated => setTenants(prev => prev.map(t => t.id === id ? updated : t)));

  const onDeleteTenant = (id) =>
    api.delete("tenants", id).then(() => setTenants(prev => prev.filter(t => t.id !== id)));

  const onDeleteLease = (id) =>
    api.delete("leases", id).then(() => setLeases(prev => prev.filter(l => l.id !== id)));

  const onDeleteTransaction = (id) =>
    api.delete("transactions", id).then(() => setTransactions(prev => prev.filter(t => t.id !== id)));

  const onDeleteInvoice = (id) =>
    api.delete("invoices", id).then(() => setInvoices(prev => prev.filter(i => i.id !== id)));

  const PAGE_TITLES = {
    dashboard:   { title: "Dashboard",        sub: "Overview of your rental portfolio" },
    properties:  { title: "Properties",       sub: "Property P&L and expense history" },
    transactions:{ title: "Transactions",     sub: "Income & expense ledger" },
    invoices:    { title: "Invoices",         sub: "Create and track tenant invoices" },
    leases:      { title: "Lease Contracts",  sub: "Track lease terms and renewals" },
    tenants:     { title: "Tenants",          sub: "Tenant contact directory" },
  };

  return (
    <>
      <style>{css}</style>
      <div className="app">
        <div className="sidebar">
          <div className="sidebar-logo">
            <h1>Property<br />Manager</h1>
            <span>Kenji Morishige</span>
          </div>
          {NAV.map(n => (
            <div key={n.id} className={`nav-item ${page === n.id ? "active" : ""}`} onClick={() => setPage(n.id)}>
              <span className="nav-icon">{n.icon}</span>
              <span>{n.label}</span>
            </div>
          ))}
        </div>

        <div className="main">
          <div className="page-header">
            <div>
              <div className="page-title">{PAGE_TITLES[page].title}</div>
              <div className="page-sub">{PAGE_TITLES[page].sub}</div>
            </div>
          </div>
          <div className="page-content">
            {loading ? (
              <div style={{ padding: 40, textAlign: "center", color: COLORS.slate }}>Loading…</div>
            ) : (
              <>
                {page === "dashboard"    && <Dashboard transactions={transactions} invoices={invoices} leases={leases} tenants={tenants} />}
                {page === "properties"  && properties.map(p => <PropertyView key={p.id} property={p} transactions={transactions} leases={leases} invoices={invoices} tenants={tenants} />)}
                {page === "transactions"&& <Transactions transactions={transactions} onAddTransaction={onAddTransaction} onDeleteTransaction={onDeleteTransaction} tenants={tenants} />}
                {page === "invoices"    && <Invoices invoices={invoices} onAddInvoice={onAddInvoice} onUpdateInvoice={onUpdateInvoice} onDeleteInvoice={onDeleteInvoice} tenants={tenants} leases={leases} />}
                {page === "leases"      && <Leases leases={leases} onAddLease={onAddLease} onDeleteLease={onDeleteLease} tenants={tenants} />}
                {page === "tenants"     && <Tenants tenants={tenants} onAddTenant={onAddTenant} onUpdateTenant={onUpdateTenant} onDeleteTenant={onDeleteTenant} />}
              </>
            )}
          </div>
        </div>
      </div>
    </>
  );
}
