// Tenants, Calendar, Maintenance, Reports

function TenantsPage({ data, route, setRoute }) {
  const { properties, tenants, store } = data;
  const [showAdd, setShowAdd] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const [deleting, setDeleting] = React.useState(null);

  // If route carries tenantId → render detail view
  if (route?.tenantId) {
    return <TenantDetail data={data} route={route} setRoute={setRoute} tenantId={route.tenantId} />;
  }

  const allTenants = Object.values(tenants);
  // Build a map of tenant_id → assigned unit/property (if any)
  const assignmentByTenant = {};
  for (const p of properties) {
    for (const u of p.units) {
      if (u.tenant) assignmentByTenant[u.tenant] = { unit: u, property: p };
    }
  }

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Mieter</h1>
          <div className="page-subtitle">{allTenants.length} {allTenants.length === 1 ? 'Mieter' : 'Mieter'} insgesamt</div>
        </div>
        <div className="page-actions">
          <button className="btn btn-primary" onClick={() => { setEditing(null); setShowAdd(true); }}><Icon.Plus /> Mieter hinzufügen</button>
        </div>
      </div>
      <TenantForm open={showAdd} onClose={() => setShowAdd(false)} store={store} initial={editing} />
      <ConfirmDialog
        open={!!deleting}
        onClose={() => setDeleting(null)}
        onConfirm={async () => { await store.deleteTenant(deleting.id); }}
        title="Mieter löschen"
        message={`„${deleting?.name}" endgültig löschen? Wohnungen werden auf Leerstand gesetzt.`}
        confirmLabel="Endgültig löschen"
      />

      {allTenants.length === 0 ? (
        <div className="empty" style={{ padding: '50px 20px', textAlign: 'center' }}>
          <div style={{ fontSize: 36, marginBottom: 8 }}>👥</div>
          <div className="empty-title">Noch keine Mieter</div>
          <div style={{ color: 'var(--ink-3)', maxWidth: 360, margin: '0 auto 16px' }}>Lege deinen ersten Mieter an. Du kannst ihn dann einer Wohnung zuordnen.</div>
          <button className="btn btn-primary" onClick={() => setShowAdd(true)}><Icon.Plus /> Erster Mieter</button>
        </div>
      ) : (
      <div className="table-wrap">
        <table className="table">
          <thead>
            <tr>
              <th>Mieter</th>
              <th>Objekt / Einheit</th>
              <th>Mieter seit</th>
              <th>Vertragsende</th>
              <th className="num">Kaution</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {allTenants.map(tenant => {
              const a = assignmentByTenant[tenant.id];
              return (
                <tr key={tenant.id} style={{ cursor: 'pointer' }} onClick={() => setRoute({ page: 'tenants', tenantId: tenant.id })}>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <div className="avatar" style={{ width: 28, height: 28, fontSize: 11 }}>{tenant.name.split(' ').map(s => s[0]).slice(0, 2).join('')}</div>
                      <div>
                        <div className="strong">{tenant.name}</div>
                        <div className="muted" style={{ fontSize: 11.5 }}>{tenant.email || tenant.phone || ''}</div>
                      </div>
                    </div>
                  </td>
                  <td onClick={e => e.stopPropagation()}>
                    {a ? (
                      <button className="btn-link" onClick={() => setRoute({ page: 'properties', propertyId: a.property.id, unitId: a.unit.id })} style={{ textAlign: 'left' }}>
                        <div className="strong">{a.property.name}</div>
                        <div className="muted" style={{ fontSize: 11.5 }}>{a.unit.label}</div>
                      </button>
                    ) : <span className="muted">— nicht zugeordnet —</span>}
                  </td>
                  <td className="muted">{tenant.since ? fmtDate(tenant.since) : '—'}</td>
                  <td>{tenant.until ? <Pill tone="warn">{fmtDate(tenant.until)}</Pill> : <span className="muted">{a ? 'unbefristet' : '—'}</span>}</td>
                  <td className="num muted">{tenant.deposit ? fmtEUR(tenant.deposit) : '—'}</td>
                  <td className="num" onClick={e => e.stopPropagation()} style={{ whiteSpace: 'nowrap' }}>
                    <button className="btn-link" onClick={() => { setEditing(tenant); setShowAdd(true); }} style={{ fontSize: 12 }}>✎</button>
                    <button className="btn-link" onClick={() => setDeleting(tenant)} style={{ fontSize: 12, marginLeft: 8, color: 'var(--neg)' }}>✕</button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      )}
    </div>
  );
}

// ───── Tenant Detail Page ─────
function TenantDetail({ data, tenantId, setRoute }) {
  const { tenants, properties, transactions, store } = data;
  const [showEdit, setShowEdit] = React.useState(false);
  const [showDelete, setShowDelete] = React.useState(false);

  const tenant = tenants[tenantId];
  if (!tenant) return <div className="page"><div className="empty">Mieter nicht gefunden.</div></div>;

  // Find unit + property
  let unit = null, property = null;
  for (const p of properties) {
    const u = p.units.find(u => u.tenant === tenantId);
    if (u) { unit = u; property = p; break; }
  }

  // Cloud documents linked to this tenant's unit
  const cloudDocs = useDocuments(unit ? { propertyId: property.id, unitId: unit.id } : {});

  // Transactions with this tenant: filter by unit_id (rent payments) OR counterparty matches name
  const nameNorm = tenant.name.toLowerCase();
  const tenantTxns = transactions.filter(t =>
    (unit && t.unitId === unit.id) ||
    (t.counterparty || '').toLowerCase().includes(nameNorm)
  );
  const incomeTxns = tenantTxns.filter(t => t.type === 'einnahme');
  const expenseTxns = tenantTxns.filter(t => t.type === 'ausgabe');
  const totalIncome = incomeTxns.reduce((s, t) => s + t.amount, 0);
  const totalExpense = expenseTxns.reduce((s, t) => s + Math.abs(t.amount), 0);
  const netRevenue = totalIncome - totalExpense;

  // Years as tenant
  const sinceDate = tenant.since ? new Date(tenant.since) : null;
  const untilDate = tenant.until ? new Date(tenant.until) : null;
  const refDate = untilDate || new Date();
  const yearsAsTenant = sinceDate ? ((refDate - sinceDate) / (1000 * 60 * 60 * 24 * 365.25)).toFixed(1) : null;
  const isActive = !untilDate || untilDate > new Date();

  // Rent saldo: expected rent (months × Kaltmiete) vs actual income
  let expectedRent = 0;
  if (unit && sinceDate) {
    const monthsActive = Math.max(0, Math.floor((refDate - sinceDate) / (1000 * 60 * 60 * 24 * 30.44)));
    expectedRent = monthsActive * (unit.rent || 0);
  }
  const rentSaldo = totalIncome - expectedRent;

  // Birthday gimmick: days until next birthday
  let bdayInfo = null;
  if (tenant.birthdate) {
    const bd = new Date(tenant.birthdate);
    const today = new Date(); today.setHours(0,0,0,0);
    const next = new Date(today.getFullYear(), bd.getMonth(), bd.getDate());
    if (next < today) next.setFullYear(next.getFullYear() + 1);
    const days = Math.round((next - today) / (1000 * 60 * 60 * 24));
    const ageNext = next.getFullYear() - bd.getFullYear();
    bdayInfo = { days, ageNext, dateNext: next };
  }

  // Contract end alert: <90 days remaining
  let contractAlert = null;
  if (untilDate && untilDate > new Date()) {
    const days = Math.round((untilDate - new Date()) / (1000 * 60 * 60 * 24));
    if (days <= 90) contractAlert = { days };
  }

  return (
    <div className="page">
      <TenantForm open={showEdit} onClose={() => setShowEdit(false)} store={store} initial={tenant} />
      <ConfirmDialog
        open={showDelete}
        onClose={() => setShowDelete(false)}
        onConfirm={async () => { await store.deleteTenant(tenant.id); setRoute({ page: 'tenants' }); }}
        title="Mieter löschen"
        message={`„${tenant.name}" endgültig löschen? Wohnung wird auf Leerstand gesetzt.`}
        confirmLabel="Endgültig löschen"
      />

      <div className="page-header">
        <div>
          <button className="btn-link" onClick={() => setRoute({ page: 'tenants' })} style={{ marginBottom: 8 }}>← Zurück zu allen Mietern</button>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 6 }}>
            <div className="avatar" style={{ width: 56, height: 56, fontSize: 22, background: 'var(--accent)', color: 'var(--accent-ink)' }}>
              {tenant.name.split(/\s+/).map(s => s[0]).filter(Boolean).slice(0, 2).join('')}
            </div>
            <div>
              <h1 className="page-title" style={{ marginBottom: 4 }}>{tenant.name}</h1>
              <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                {isActive ? <Pill tone="pos">Aktiver Mieter</Pill> : <Pill tone="default">Ehemaliger Mieter</Pill>}
                {yearsAsTenant && <span className="muted" style={{ fontSize: 13 }}>seit {yearsAsTenant} {Number(yearsAsTenant) === 1 ? 'Jahr' : 'Jahren'}</span>}
                {!unit && <Pill tone="warn">Keiner Wohnung zugeordnet</Pill>}
              </div>
            </div>
          </div>
        </div>
        <div className="page-actions">
          {tenant.email && <a className="btn" href={`mailto:${tenant.email}`}>✉ E-Mail</a>}
          {tenant.phone && <a className="btn" href={`tel:${tenant.phone}`}>📞 Anrufen</a>}
          <button className="btn btn-ghost" onClick={() => setShowEdit(true)}>Bearbeiten</button>
          <button className="btn btn-ghost" onClick={() => setShowDelete(true)} style={{ color: 'var(--neg)' }}>Löschen</button>
        </div>
      </div>

      {/* Alerts */}
      {(bdayInfo?.days <= 30 || contractAlert) && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 24 }}>
          {bdayInfo && bdayInfo.days <= 30 && (
            <div style={{ padding: '12px 16px', background: 'var(--accent-soft)', border: '1px solid var(--accent)', borderRadius: 'var(--radius)', fontSize: 13 }}>
              🎂 <strong>Geburtstag {bdayInfo.days === 0 ? 'heute' : bdayInfo.days === 1 ? 'morgen' : `in ${bdayInfo.days} Tagen`}</strong> — {bdayInfo.ageNext}. Geburtstag am {bdayInfo.dateNext.toLocaleDateString('de-DE')}
            </div>
          )}
          {contractAlert && (
            <div style={{ padding: '12px 16px', background: 'rgba(168,121,48,0.08)', border: '1px solid var(--warn)', borderRadius: 'var(--radius)', fontSize: 13 }}>
              ⚠ <strong>Vertragsende in {contractAlert.days} Tagen</strong> — Verlängerung oder Neuvermietung jetzt anstoßen
            </div>
          )}
        </div>
      )}

      {/* KPI cards */}
      <div className="kpi-grid">
        <div className="kpi">
          <div className="kpi-label">Mieteinnahmen gesamt</div>
          <div className="kpi-value" style={{ color: 'var(--pos)' }}>{fmtEUR(totalIncome)}</div>
          <div className="kpi-meta">{incomeTxns.length} Buchungen</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Ausgaben mit Bezug</div>
          <div className="kpi-value" style={{ color: 'var(--neg)' }}>{fmtEUR(totalExpense)}</div>
          <div className="kpi-meta">{expenseTxns.length} Buchungen (z.B. Reparaturen)</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Netto-Beitrag</div>
          <div className="kpi-value" style={{ color: netRevenue >= 0 ? 'var(--pos)' : 'var(--neg)' }}>{fmtEUR(netRevenue)}</div>
          <div className="kpi-meta">seit Mietbeginn</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Mietsaldo</div>
          <div className="kpi-value" style={{ color: rentSaldo >= -10 ? 'var(--pos)' : 'var(--neg)', fontSize: 22 }}>
            {rentSaldo >= -10 ? '✓ ausgeglichen' : fmtEUR(rentSaldo)}
          </div>
          <div className="kpi-meta">{unit ? `Soll: ${fmtEUR(expectedRent)}` : 'keine Wohnung'}</div>
        </div>
      </div>

      <div className="two-col" style={{ marginTop: 24 }}>
        {/* Left column: Stammdaten + Wohnung */}
        <div>
          <div className="section">
            <div className="section-header"><h2 className="section-title">Stammdaten</h2></div>
            <div className="form-card">
              <div className="kv-list">
                <div className="kv"><span className="k">E-Mail</span><span className="v">{tenant.email || '—'}</span></div>
                <div className="kv"><span className="k">Telefon</span><span className="v">{tenant.phone || '—'}</span></div>
                <div className="kv"><span className="k">Geburtsdatum</span><span className="v">{tenant.birthdate ? fmtDate(tenant.birthdate) : '—'}</span></div>
                <div className="kv"><span className="k">Mietbeginn</span><span className="v">{tenant.since ? fmtDate(tenant.since) : '—'}</span></div>
                <div className="kv"><span className="k">Mietende</span><span className="v">{tenant.until ? fmtDate(tenant.until) : 'unbefristet'}</span></div>
                <div className="kv"><span className="k">Kaution</span><span className="v">{tenant.deposit ? fmtEUR(tenant.deposit) : '—'}</span></div>
                <div className="kv"><span className="k">IBAN</span><span className="v" style={{ fontVariantNumeric: 'normal' }}>{tenant.iban || '—'}</span></div>
                <div className="kv"><span className="k">Vorherige Adresse</span><span className="v" style={{ fontVariantNumeric: 'normal' }}>{tenant.addressPrev || '—'}</span></div>
              </div>
            </div>
          </div>

          {tenant.notes && (
            <div className="section">
              <div className="section-header"><h2 className="section-title">Notiz</h2></div>
              <div style={{ fontFamily: 'var(--font-serif)', fontSize: 16, fontStyle: 'italic', color: 'var(--ink-2)', maxWidth: 600, lineHeight: 1.6, padding: '12px 0' }}>
                „{tenant.notes}"
              </div>
            </div>
          )}
        </div>

        {/* Right column: Wohnung-Karte */}
        <div>
          <div className="section">
            <div className="section-header"><h2 className="section-title">Wohnung</h2></div>
            {unit && property ? (
              <div className="side-card">
                <h3>{unit.label}</h3>
                <div style={{ fontSize: 13, color: 'var(--ink-3)' }}>{property.name} · {property.address}</div>
                <div className="kv-list" style={{ marginTop: 12 }}>
                  <div className="kv"><span className="k">Etage / Lage</span><span className="v">{unit.floor || '—'}</span></div>
                  <div className="kv"><span className="k">Wohnfläche</span><span className="v">{unit.size ? `${unit.size} m²` : '—'}</span></div>
                  <div className="kv"><span className="k">Zimmer</span><span className="v">{unit.rooms || '—'}</span></div>
                  <div className="kv"><span className="k">Kaltmiete</span><span className="v">{unit.rent ? `${fmtEUR(unit.rent)}/Monat` : '—'}</span></div>
                </div>
                <button className="btn btn-primary" onClick={() => setRoute({ page: 'properties', propertyId: property.id, unitId: unit.id })} style={{ marginTop: 12 }}>
                  Zur Wohnung →
                </button>
              </div>
            ) : (
              <div className="empty" style={{ padding: 24 }}>
                <div className="empty-title">Keiner Wohnung zugeordnet</div>
                <div style={{ color: 'var(--ink-3)', fontSize: 12 }}>Geh zu einem Objekt → Wohnung → Bearbeiten → Mieter wählen.</div>
              </div>
            )}
          </div>

          <div className="section">
            <div className="section-header"><h2 className="section-title">Schnellaktionen</h2></div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {unit && (
                <button className="btn btn-ghost" style={{ justifyContent: 'flex-start' }} onClick={() => setRoute({ page: 'contracts', contractWizard: 'kuendigung-vermieter', propertyId: property.id, unitId: unit.id })}>
                  <Icon.Doc /> Kündigungsschreiben erstellen
                </button>
              )}
              {unit && (
                <button className="btn btn-ghost" style={{ justifyContent: 'flex-start' }} onClick={() => setRoute({ page: 'contracts', contractWizard: 'mieterhoehung', propertyId: property.id, unitId: unit.id })}>
                  <Icon.Doc /> Mieterhöhung berechnen
                </button>
              )}
              {tenant.email && (
                <a className="btn btn-ghost" href={`mailto:${tenant.email}?subject=Anfrage&body=Hallo ${tenant.name},`} style={{ justifyContent: 'flex-start' }}>
                  ✉ E-Mail schreiben
                </a>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* Buchungen */}
      <div className="section">
        <div className="section-header">
          <h2 className="section-title">Buchungen mit diesem Mieter</h2>
          <span className="muted" style={{ fontSize: 12 }}>{tenantTxns.length} {tenantTxns.length === 1 ? 'Eintrag' : 'Einträge'}</span>
        </div>
        {tenantTxns.length === 0 ? (
          <div className="empty" style={{ padding: 24 }}>
            <div style={{ color: 'var(--ink-3)' }}>Noch keine Buchungen mit Bezug zu diesem Mieter.</div>
          </div>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead><tr><th>Datum</th><th>Beschreibung</th><th>Kategorie</th><th>Empfänger</th><th className="num">Betrag</th></tr></thead>
              <tbody>
                {tenantTxns.slice(0, 100).map(t => (
                  <tr key={t.id}>
                    <td className="muted" style={{ whiteSpace: 'nowrap' }}>{fmtDateShort(t.date)}</td>
                    <td className="strong">{t.description || '—'}</td>
                    <td>{t.category ? <Pill>{t.category}</Pill> : <span className="muted">—</span>}</td>
                    <td className="muted">{t.counterparty || '—'}</td>
                    <td className="num strong" style={{ color: t.amount >= 0 ? 'var(--pos)' : 'var(--neg)', whiteSpace: 'nowrap' }}>
                      {t.amount >= 0 ? '+' : ''}{fmtEUR(t.amount)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Cloud documents linked to the unit */}
      {unit && cloudDocs.items.length > 0 && (
        <div className="section">
          <div className="section-header">
            <h2 className="section-title">Dokumente</h2>
            <span className="muted" style={{ fontSize: 12 }}>{cloudDocs.items.length} aus Cloud</span>
          </div>
          <div>
            {cloudDocs.items.map(doc => (
              <div key={doc.id} className="doc-row">
                <div className="doc-icon"></div>
                <div>
                  <a href={viewDocumentUrl(doc.id)} target="_blank" rel="noopener" style={{ fontWeight: 500, color: 'var(--ink)', textDecoration: 'none' }}>{doc.name}</a>
                  <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 2 }}>{(doc.sizeBytes / 1024).toFixed(0)} KB · {fmtDateShort(doc.uploadedAt)}</div>
                </div>
                <Pill>{doc.category || 'Cloud'}</Pill>
                <a href={downloadDocumentUrl(doc.id)} className="doc-download-btn" download>↓</a>
                <span></span>
                <span></span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function CalendarPage({ data }) {
  const { reminders, transactions, properties, store } = data;
  const today = new Date();
  const [cursor, setCursor] = React.useState(new Date(today.getFullYear(), today.getMonth(), 1));
  const [showForm, setShowForm] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const [deleting, setDeleting] = React.useState(null);
  const hasRentDue = properties?.some(p => p.units.some(u => u.rent && u.rent > 0));

  const openAdd = () => { setEditing(null); setShowForm(true); };
  const openEdit = (r) => { setEditing(r); setShowForm(true); };

  const year = cursor.getFullYear();
  const month = cursor.getMonth();
  const firstDay = new Date(year, month, 1);
  const startWeekday = (firstDay.getDay() + 6) % 7; // Mon=0
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const cells = [];
  for (let i = 0; i < startWeekday; i++) {
    const d = new Date(year, month, -startWeekday + i + 1);
    cells.push({ date: d, muted: true });
  }
  for (let i = 1; i <= daysInMonth; i++) {
    cells.push({ date: new Date(year, month, i), muted: false });
  }
  while (cells.length % 7 !== 0) {
    const last = cells[cells.length - 1].date;
    cells.push({ date: new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1), muted: true });
  }

  const monthName = cursor.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' });

  const eventsForDate = (d) => {
    const key = d.toISOString().slice(0, 10);
    const evs = reminders.filter(r => r.date === key).map(r => ({ ...r, kind: 'reminder' }));
    if (d.getDate() === 1 && hasRentDue) evs.push({ id: `rent-${key}`, title: 'Mieteingänge', kind: 'rent' });
    return evs;
  };

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Kalender</h1>
          <div className="page-subtitle">Fristen, Wartungen, Mietzahlungen</div>
        </div>
        <div className="page-actions">
          <button className="btn" onClick={() => setCursor(new Date(year, month - 1, 1))}>‹</button>
          <button className="btn" onClick={() => setCursor(new Date(today.getFullYear(), today.getMonth(), 1))}>{monthName}</button>
          <button className="btn" onClick={() => setCursor(new Date(year, month + 1, 1))}>›</button>
          <button className="btn btn-primary" onClick={openAdd}><Icon.Plus /> Termin</button>
        </div>
      </div>
      <ReminderForm open={showForm} onClose={() => setShowForm(false)} store={store} properties={properties} initial={editing} />
      <ConfirmDialog
        open={!!deleting}
        onClose={() => setDeleting(null)}
        onConfirm={async () => { await store.deleteReminder(deleting.id); }}
        title="Termin löschen"
        message={`„${deleting?.title}" endgültig löschen?`}
        confirmLabel="Endgültig löschen"
      />

      <div className="cal-grid">
        {['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'].map(d => <div key={d} className="cal-head">{d}</div>)}
        {cells.map((c, i) => {
          const isToday = c.date.toDateString() === today.toDateString();
          const evs = c.muted ? [] : eventsForDate(c.date);
          return (
            <div key={i} className={`cal-cell ${c.muted ? 'muted' : ''} ${isToday ? 'today' : ''}`}>
              <div style={{ display: 'flex', alignItems: 'center', height: 22 }}>
                <span className="cal-num">{c.date.getDate()}</span>
              </div>
              {evs.map((e, j) => (
                <div key={j} className={`cal-event ${e.priority === 'hoch' ? 'warn' : ''}`}>
                  {e.title}
                </div>
              ))}
            </div>
          );
        })}
      </div>

      <div className="section" style={{ marginTop: 48 }}>
        <div className="section-header">
          <h2 className="section-title">Anstehende Fristen</h2>
        </div>
        {reminders.length === 0 ? (
          <div className="empty" style={{ padding: '40px 20px', textAlign: 'center' }}>
            <div className="empty-title">Noch keine Termine</div>
            <div style={{ color: 'var(--ink-3)', maxWidth: 360, margin: '0 auto 16px' }}>Lege Erinnerungen an Wartungen, Vertragsfristen, Versicherungserneuerungen etc. an.</div>
            <button className="btn btn-primary" onClick={openAdd}><Icon.Plus /> Erster Termin</button>
          </div>
        ) : (
        <div className="table-wrap">
          <table className="table">
            <thead><tr><th>Datum</th><th>Titel</th><th>Kategorie</th><th>Priorität</th><th>Objekt</th><th></th></tr></thead>
            <tbody>
              {[...reminders].sort((a, b) => a.date.localeCompare(b.date)).map(r => {
                const prop = properties.find(p => p.id === r.propertyId);
                return (
                  <tr key={r.id}>
                    <td className="strong">{fmtDate(r.date)}</td>
                    <td>{r.title}</td>
                    <td>{r.category && <Pill>{r.category}</Pill>}</td>
                    <td>
                      {r.priority === 'hoch' ? <Pill tone="warn">Hoch</Pill> : r.priority === 'mittel' ? <Pill>Mittel</Pill> : <Pill>Niedrig</Pill>}
                    </td>
                    <td className="muted">{prop ? prop.name : '—'}</td>
                    <td style={{ whiteSpace: 'nowrap' }}>
                      <button className="btn-link" onClick={() => openEdit(r)} title="Bearbeiten">✎</button>
                      <button className="btn-link" onClick={() => setDeleting(r)} title="Löschen" style={{ color: 'var(--neg)', marginLeft: 8 }}>✕</button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        )}
      </div>
    </div>
  );
}

function MaintenancePage({ data, setRoute }) {
  const { maintenance, properties, contacts, store } = data;
  const [showForm, setShowForm] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const [deleting, setDeleting] = React.useState(null);

  const openAdd = () => { setEditing(null); setShowForm(true); };
  const openEdit = (m) => { setEditing(m); setShowForm(true); };

  const open = maintenance.filter(m => m.status !== 'erledigt');

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Wartung & Reparatur</h1>
          <div className="page-subtitle">{open.length} {open.length === 1 ? 'offener Vorgang' : 'offene Vorgänge'} · {maintenance.length} insgesamt</div>
        </div>
        <div className="page-actions">
          <button className="btn btn-primary" onClick={openAdd}><Icon.Plus /> Vorgang anlegen</button>
        </div>
      </div>
      <MaintenanceForm open={showForm} onClose={() => setShowForm(false)} store={store} properties={properties} contacts={contacts} initial={editing} />
      <ConfirmDialog
        open={!!deleting}
        onClose={() => setDeleting(null)}
        onConfirm={async () => { await store.deleteMaintenance(deleting.id); }}
        title="Wartungsvorgang löschen"
        message={`„${deleting?.title}" endgültig löschen?`}
        confirmLabel="Endgültig löschen"
      />

      {maintenance.length === 0 ? (
        <div className="empty" style={{ padding: '50px 20px', textAlign: 'center' }}>
          <div style={{ fontSize: 36, marginBottom: 8 }}>🔧</div>
          <div className="empty-title">Keine Wartungsvorgänge</div>
          <div style={{ color: 'var(--ink-3)', maxWidth: 380, margin: '0 auto 16px' }}>Lege geplante oder akute Reparaturen an, weise sie einem Handwerker zu, verfolge den Status.</div>
          <button className="btn btn-primary" onClick={openAdd}><Icon.Plus /> Erster Vorgang</button>
        </div>
      ) : (
      <div className="table-wrap">
        <table className="table">
          <thead><tr><th>Titel</th><th>Objekt</th><th>Beauftragt an</th><th>Status</th><th>Fällig</th><th className="num">Kosten</th><th></th></tr></thead>
          <tbody>
            {maintenance.map(m => {
              const prop = properties.find(p => p.id === m.propertyId);
              const unit = prop?.units.find(u => u.id === m.unitId);
              const contact = contacts?.find(c => c.id === m.contactId);
              const tenantId = unit?.tenant;
              return (
                <tr key={m.id}>
                  <td className="strong">{m.title}</td>
                  <td className="muted">{prop ? prop.name : '—'}{unit ? ` · ${unit.label}` : ''}</td>
                  <td className="muted">{contact ? contact.company : '—'}</td>
                  <td>
                    {m.status === 'erledigt' ? <Pill tone="pos">Erledigt</Pill>
                      : m.status === 'in-arbeit' ? <Pill tone="warn">In Arbeit</Pill>
                      : <Pill>Geplant</Pill>}
                  </td>
                  <td className="muted">{m.dueDate ? fmtDate(m.dueDate) : '—'}</td>
                  <td className="num strong">{m.cost ? fmtEUR(m.cost) : '—'}</td>
                  <td style={{ whiteSpace: 'nowrap' }}>
                    <UploadButton
                      className="btn-link"
                      label="↑"
                      meta={{ propertyId: m.propertyId || null, unitId: m.unitId || null, scope: m.unitId ? 'einheit' : 'allgemein', category: 'Rechnung' }}
                      propertyContext={prop?.name}
                      unitContext={unit?.label}
                      onUpload={() => store.reload()}
                    />
                    <button className="btn-link" onClick={() => openEdit(m)} title="Bearbeiten" style={{ marginLeft: 8 }}>✎</button>
                    <button className="btn-link" onClick={() => setDeleting(m)} title="Löschen" style={{ color: 'var(--neg)', marginLeft: 8 }}>✕</button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      )}
    </div>
  );
}

// ─── Steuerberater-Export Section ────────────────────────────────────
// Wählt Monat + Objekt aus, lädt ZIP mit Buchungen-CSV + verknüpften Belegen.
function SteuerExportSection({ properties, transactions }) {
  const today = new Date();
  const [year, setYear] = React.useState(today.getFullYear());
  const [month, setMonth] = React.useState(today.getMonth() === 0 ? 12 : today.getMonth()); // default: letzter Monat
  React.useEffect(() => {
    if (today.getMonth() === 0 && month === 12) setYear(today.getFullYear() - 1);
  }, []);
  const [propertyId, setPropertyId] = React.useState('');

  const ym = `${year}-${String(month).padStart(2, '0')}`;
  const txInMonth = transactions.filter(t => t.date.startsWith(ym) && (!propertyId || t.propertyId === propertyId));
  const withDocsCount = txInMonth.filter(t => (t.documentCount || 0) > 0).length;
  const totalIncome = txInMonth.filter(t => t.type === 'einnahme').reduce((s, t) => s + t.amount, 0);
  const totalExpense = txInMonth.filter(t => t.type === 'ausgabe').reduce((s, t) => s + Math.abs(t.amount), 0);

  const monthLabels = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'];
  const downloadUrl = window.monthlyExportZipUrl({ year, month, propertyId: propertyId || undefined });

  return (
    <div className="section" style={{ marginBottom: 24, padding: 18, background: 'var(--accent-soft)', border: '1px solid var(--accent)', borderRadius: 'var(--radius)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: 16 }}>
        <div style={{ flex: 1, minWidth: 280 }}>
          <h2 className="section-title" style={{ margin: 0, marginBottom: 4 }}>📦 Steuerberater-Mappe</h2>
          <div style={{ fontSize: 12.5, color: 'var(--ink-3)' }}>
            ZIP mit Buchungen + Belegen + Zusammenfassung — direkt zum Versand an deinen Steuerberater
          </div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          <select className="form-input" style={{ width: 140 }} value={month} onChange={e => setMonth(Number(e.target.value))}>
            {monthLabels.map((label, i) => <option key={i} value={i + 1}>{label}</option>)}
          </select>
          <select className="form-input" style={{ width: 100 }} value={year} onChange={e => setYear(Number(e.target.value))}>
            {Array.from({ length: 6 }, (_, i) => today.getFullYear() - 3 + i).map(y => <option key={y} value={y}>{y}</option>)}
          </select>
          <select className="form-input" style={{ width: 200 }} value={propertyId} onChange={e => setPropertyId(e.target.value)}>
            <option value="">Alle Objekte</option>
            {properties.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
          </select>
        </div>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 24, marginTop: 14, padding: '12px 16px', background: 'var(--bg-elev)', borderRadius: 'var(--radius)', flexWrap: 'wrap' }}>
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Buchungen</div>
          <div style={{ fontSize: 18, fontWeight: 500 }}>{txInMonth.length}</div>
        </div>
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Mit Beleg</div>
          <div style={{ fontSize: 18, fontWeight: 500, color: withDocsCount === txInMonth.length ? 'var(--pos)' : 'var(--warn)' }}>
            {withDocsCount} / {txInMonth.length}
          </div>
        </div>
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Einnahmen</div>
          <div style={{ fontSize: 18, fontWeight: 500, color: 'var(--pos)' }}>{fmtEUR(totalIncome)}</div>
        </div>
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Ausgaben</div>
          <div style={{ fontSize: 18, fontWeight: 500, color: 'var(--neg)' }}>{fmtEUR(totalExpense)}</div>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center' }}>
          {txInMonth.length > 0 && withDocsCount < txInMonth.length && (
            <span style={{ fontSize: 11.5, color: 'var(--warn)' }}>⚠ {txInMonth.length - withDocsCount} ohne Beleg</span>
          )}
          <a
            href={downloadUrl}
            className="btn btn-primary"
            download
            style={{ pointerEvents: txInMonth.length === 0 ? 'none' : 'auto', opacity: txInMonth.length === 0 ? 0.5 : 1 }}
          >
            📥 ZIP herunterladen
          </a>
        </div>
      </div>
    </div>
  );
}

// ─── Berichte / Reports ─────────────────────────────────────────────
// Filterleiste oben (Zeitraum-Presets + Custom + Objekt-Filter), KPI-Karten,
// Cashflow-Chart, gefilterte Tx-Tabelle mit Klick-zu-Bearbeiten + Löschen,
// Pro-Objekt + Kategorien-Auswertung, CSV-Export.

const RANGE_PRESETS = [
  { id: 'thisMonth',  label: 'Aktueller Monat' },
  { id: 'lastMonth',  label: 'Letzter Monat' },
  { id: 'thisQuarter',label: 'Aktuelles Quartal' },
  { id: 'thisYear',   label: 'Aktuelles Jahr' },
  { id: 'lastYear',   label: 'Letztes Jahr' },
  { id: 'last12',     label: 'Letzte 12 Monate' },
  { id: 'all',        label: 'Alles' },
  { id: 'custom',     label: 'Benutzerdefiniert' },
];

function rangeForPreset(preset, custom) {
  const today = new Date();
  const y = today.getFullYear();
  const m = today.getMonth();
  const fmt = (d) => d.toISOString().slice(0, 10);
  switch (preset) {
    case 'thisMonth':   return { from: fmt(new Date(y, m, 1)),     to: fmt(new Date(y, m + 1, 0)) };
    case 'lastMonth':   return { from: fmt(new Date(y, m - 1, 1)), to: fmt(new Date(y, m, 0)) };
    case 'thisQuarter':{ const qs = Math.floor(m / 3) * 3; return { from: fmt(new Date(y, qs, 1)), to: fmt(new Date(y, qs + 3, 0)) }; }
    case 'thisYear':    return { from: `${y}-01-01`,                 to: `${y}-12-31` };
    case 'lastYear':    return { from: `${y - 1}-01-01`,             to: `${y - 1}-12-31` };
    case 'last12':      return { from: fmt(new Date(y, m - 11, 1)),  to: fmt(today) };
    case 'all':         return { from: '1900-01-01',                 to: '2999-12-31' };
    case 'custom':      return custom || { from: '', to: '' };
    default:            return { from: `${y}-01-01`, to: `${y}-12-31` };
  }
}

function downloadCsv(filename, rows) {
  const escape = (v) => {
    const s = v == null ? '' : String(v);
    return /[";,\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
  };
  const csv = rows.map(r => r.map(escape).join(';')).join('\r\n');
  const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url; a.download = filename;
  document.body.appendChild(a);
  a.click();
  setTimeout(() => { URL.revokeObjectURL(url); a.remove(); }, 0);
}

function SmartBarChart({ months }) {
  // Empty / no data → nice empty state instead of broken axes
  if (months.length === 0) {
    return <div className="empty" style={{ padding: 40 }}>Keine Buchungen im gewählten Zeitraum.</div>;
  }
  const W = 1100, H = 240;
  const pad = { l: 56, r: 16, t: 12, b: 28 };
  const cw = W - pad.l - pad.r, ch = H - pad.t - pad.b;
  const maxRaw = Math.max(0, ...months.map(d => Math.max(d.income, d.expense)));
  if (maxRaw === 0) {
    return <div className="empty" style={{ padding: 40 }}>Keine Werte > 0 im gewählten Zeitraum.</div>;
  }
  // Nice axis: auto-scale to a power-of-10 step
  const niceStep = (raw) => {
    const e = Math.pow(10, Math.floor(Math.log10(raw)));
    const m = raw / e;
    if (m < 1.5) return e * 0.2;
    if (m < 3)   return e * 0.5;
    if (m < 7)   return e;
    return e * 2;
  };
  const step = niceStep(maxRaw);
  const niceMax = Math.ceil(maxRaw / step) * step;
  const nTicks = Math.round(niceMax / step);
  const ticks = Array.from({ length: nTicks + 1 }, (_, i) => i * step);

  const bw = cw / months.length;
  const barW = Math.min(28, bw * 0.32);
  const fmtAxis = (v) => v >= 1000 ? `${(v / 1000).toFixed(v >= 10000 ? 0 : 1)}k` : String(v);

  return (
    <div className="chart-frame" style={{ overflowX: 'auto' }}>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', minWidth: 480, height: 'auto', display: 'block' }} preserveAspectRatio="none">
        {/* Grid lines */}
        {ticks.map((t, i) => {
          const y = pad.t + ch - (t / niceMax) * ch;
          return <line key={i} x1={pad.l} x2={W - pad.r} y1={y} y2={y} stroke="var(--line-2)" strokeWidth="1" />;
        })}
        {/* Y-axis labels */}
        {ticks.map((t, i) => {
          const y = pad.t + ch - (t / niceMax) * ch;
          return <text key={i} x={pad.l - 8} y={y + 4} textAnchor="end" fontSize="10" fill="var(--ink-4)">{fmtAxis(t)}</text>;
        })}
        {/* X-axis labels */}
        {months.map((d, i) => (
          <text key={i} x={pad.l + bw * i + bw / 2} y={H - 8} textAnchor="middle" fontSize="10" fill="var(--ink-3)">{d.label}</text>
        ))}
        {/* Bars */}
        {months.map((d, i) => {
          const xc = pad.l + bw * i + bw / 2;
          const incH = (d.income / niceMax) * ch;
          const expH = (d.expense / niceMax) * ch;
          return (
            <g key={i}>
              <rect x={xc - barW - 1} y={pad.t + ch - incH} width={barW} height={Math.max(0, incH)} rx="1" fill="var(--accent)" />
              <rect x={xc + 1} y={pad.t + ch - expH} width={barW} height={Math.max(0, expH)} rx="1" fill="var(--neg)" opacity="0.7" />
            </g>
          );
        })}
        {/* Net line */}
        <polyline
          fill="none" stroke="var(--ink)" strokeWidth="1.5"
          points={months.map((d, i) => {
            const x = pad.l + bw * i + bw / 2;
            const y = pad.t + ch - Math.max(0, d.net) / niceMax * ch;
            return `${x},${y}`;
          }).join(' ')}
        />
      </svg>
      <div style={{ display: 'flex', justifyContent: 'center', gap: 16, fontSize: 12, color: 'var(--ink-3)', marginTop: 8 }}>
        <span><span style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--accent)', marginRight: 4, borderRadius: 2 }}/>Einnahmen</span>
        <span><span style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--neg)', opacity: 0.7, marginRight: 4, borderRadius: 2 }}/>Ausgaben</span>
        <span><span style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--ink)', marginRight: 4, verticalAlign: 'middle' }}/>Netto</span>
      </div>
    </div>
  );
}

function ReportsPage({ data }) {
  const { properties, transactions, store } = data;

  const [preset, setPreset] = React.useState('thisYear');
  const [custom, setCustom] = React.useState({ from: '', to: '' });
  const [propertyFilter, setPropertyFilter] = React.useState('all');
  const [typeFilter, setTypeFilter] = React.useState('all'); // all | einnahme | ausgabe
  const [search, setSearch] = React.useState('');
  const [sortBy, setSortBy] = React.useState('date-desc');
  const [editingTx, setEditingTx] = React.useState(null);
  const [showTxForm, setShowTxForm] = React.useState(false);
  const [deletingTx, setDeletingTx] = React.useState(null);

  const range = rangeForPreset(preset, custom);

  // Apply filters
  let filtered = transactions;
  filtered = filtered.filter(t => t.date >= range.from && t.date <= range.to);
  if (propertyFilter !== 'all')
    filtered = filtered.filter(t => t.propertyId === propertyFilter);
  if (typeFilter !== 'all')
    filtered = filtered.filter(t => t.type === typeFilter);
  if (search.trim()) {
    const q = search.trim().toLowerCase();
    filtered = filtered.filter(t =>
      (t.description || '').toLowerCase().includes(q) ||
      (t.counterparty || '').toLowerCase().includes(q) ||
      (t.category || '').toLowerCase().includes(q)
    );
  }

  // Sort
  const sorted = [...filtered].sort((a, b) => {
    switch (sortBy) {
      case 'date-asc':   return a.date.localeCompare(b.date);
      case 'date-desc':  return b.date.localeCompare(a.date);
      case 'amount-asc': return Math.abs(a.amount) - Math.abs(b.amount);
      case 'amount-desc':return Math.abs(b.amount) - Math.abs(a.amount);
      default: return 0;
    }
  });

  // Aggregate totals
  const totalIncome  = filtered.filter(t => t.type === 'einnahme').reduce((s, t) => s + t.amount, 0);
  const totalExpense = filtered.filter(t => t.type === 'ausgabe').reduce((s, t) => s + Math.abs(t.amount), 0);
  const totalNet     = totalIncome - totalExpense;
  const txCount      = filtered.length;
  const uncategorizedCount = filtered.filter(t => !t.category).length;

  // Monthly aggregation for chart
  const monthMap = new Map();
  filtered.forEach(t => {
    const key = t.date.slice(0, 7);
    if (!monthMap.has(key)) monthMap.set(key, { key, income: 0, expense: 0 });
    const e = monthMap.get(key);
    if (t.type === 'einnahme') e.income += t.amount;
    else e.expense += Math.abs(t.amount);
  });
  const months = Array.from(monthMap.values())
    .sort((a, b) => a.key.localeCompare(b.key))
    .map(m => ({
      ...m,
      net: m.income - m.expense,
      label: new Date(m.key + '-01').toLocaleDateString('de-DE', { month: 'short', year: '2-digit' }),
    }));

  // Per-property breakdown
  const propRows = properties.map(p => {
    const propTxns = filtered.filter(t => t.propertyId === p.id);
    const inc = propTxns.filter(t => t.type === 'einnahme').reduce((s, t) => s + t.amount, 0);
    const exp = propTxns.filter(t => t.type === 'ausgabe').reduce((s, t) => s + Math.abs(t.amount), 0);
    const monthlyRent = p.units.reduce((s, u) => s + (u.rent || 0), 0);
    const grossYield = p.purchasePrice > 0 ? ((monthlyRent * 12) / p.purchasePrice * 100) : 0;
    return { ...p, income: inc, expense: exp, net: inc - exp, count: propTxns.length, grossYield };
  }).filter(p => p.count > 0 || propertyFilter === p.id || propertyFilter === 'all');
  const maxPropIncome = Math.max(1, ...propRows.map(p => p.income));

  // Per-category breakdown (expenses only)
  const catMap = {};
  filtered.filter(t => t.type === 'ausgabe').forEach(t => {
    const c = t.category || 'Ohne Kategorie';
    catMap[c] = (catMap[c] || 0) + Math.abs(t.amount);
  });
  const catRows = Object.entries(catMap).sort((a, b) => b[1] - a[1]);
  const maxCat = catRows.length ? catRows[0][1] : 1;

  const exportCsv = () => {
    const fname = `hausgut-buchungen_${range.from}_${range.to}.csv`;
    const rows = [['Datum', 'Art', 'Beschreibung', 'Empfänger', 'Kategorie', 'Objekt', 'Betrag']];
    sorted.forEach(t => {
      const prop = properties.find(p => p.id === t.propertyId);
      rows.push([
        t.date,
        t.type === 'einnahme' ? 'Einnahme' : 'Ausgabe',
        t.description || '',
        t.counterparty || '',
        t.category || '',
        prop ? prop.name : '',
        t.amount.toFixed(2).replace('.', ','),
      ]);
    });
    downloadCsv(fname, rows);
  };

  // Empty: no transactions at all
  if (transactions.length === 0) {
    return (
      <div className="page">
        <div className="page-header"><div><h1 className="page-title">Berichte</h1><div className="page-subtitle">Cashflow, Rendite, Steuerübersicht</div></div></div>
        <div className="empty" style={{ padding: '60px 20px', textAlign: 'center' }}>
          <div style={{ fontSize: 36, marginBottom: 8 }}>📊</div>
          <div className="empty-title">Noch keine Buchungen</div>
          <div style={{ color: 'var(--ink-3)', maxWidth: 360, margin: '0 auto' }}>Erfasse Buchungen oder importiere eine Bank-CSV — dann werden hier Auswertungen erscheinen.</div>
        </div>
      </div>
    );
  }

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Berichte</h1>
          <div className="page-subtitle">{txCount} {txCount === 1 ? 'Buchung' : 'Buchungen'} im gewählten Zeitraum</div>
        </div>
        <div className="page-actions">
          <button className="btn" onClick={exportCsv} disabled={sorted.length === 0}>📥 CSV exportieren</button>
        </div>
      </div>
      <TransactionForm
        open={showTxForm}
        onClose={() => { setShowTxForm(false); setEditingTx(null); }}
        store={store}
        properties={properties}
        initial={editingTx}
      />
      <ConfirmDialog
        open={!!deletingTx}
        onClose={() => setDeletingTx(null)}
        onConfirm={async () => { await store.deleteTransaction(deletingTx.id); }}
        title="Buchung löschen"
        message={`„${deletingTx?.description || deletingTx?.category || 'Buchung'}" über ${deletingTx ? fmtEUR(deletingTx.amount) : ''} endgültig löschen?`}
        confirmLabel="Endgültig löschen"
      />

      {/* Steuerberater-Export */}
      <SteuerExportSection properties={properties} transactions={transactions} />

      {/* Filterleiste */}
      <div className="section" style={{ background: 'var(--bg-sunken)', padding: 16, borderRadius: 'var(--radius)' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {RANGE_PRESETS.map(p => (
              <button
                key={p.id}
                className={`btn btn-sm ${preset === p.id ? 'btn-primary' : 'btn-ghost'}`}
                onClick={() => setPreset(p.id)}
              >{p.label}</button>
            ))}
          </div>
          {preset === 'custom' && (
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
              <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>Von</span>
              <input type="date" className="form-input" style={{ maxWidth: 160 }} value={custom.from} onChange={e => setCustom(c => ({ ...c, from: e.target.value }))} />
              <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>bis</span>
              <input type="date" className="form-input" style={{ maxWidth: 160 }} value={custom.to} onChange={e => setCustom(c => ({ ...c, to: e.target.value }))} />
            </div>
          )}
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            <select className="form-input" style={{ maxWidth: 240 }} value={propertyFilter} onChange={e => setPropertyFilter(e.target.value)}>
              <option value="all">Alle Objekte</option>
              {properties.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
            </select>
            <select className="form-input" style={{ maxWidth: 160 }} value={typeFilter} onChange={e => setTypeFilter(e.target.value)}>
              <option value="all">Alle Buchungen</option>
              <option value="einnahme">Nur Einnahmen</option>
              <option value="ausgabe">Nur Ausgaben</option>
            </select>
            <input
              className="form-input"
              style={{ flex: 1, minWidth: 200 }}
              placeholder="Suche in Beschreibung / Empfänger / Kategorie…"
              value={search}
              onChange={e => setSearch(e.target.value)}
            />
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>
            Zeitraum: <strong>{range.from === '1900-01-01' ? '—' : range.from}</strong> bis <strong>{range.to === '2999-12-31' ? '—' : range.to}</strong>
          </div>
        </div>
      </div>

      {/* KPI-Karten */}
      <div className="kpi-grid" style={{ marginTop: 24 }}>
        <div className="kpi">
          <div className="kpi-label">Einnahmen</div>
          <div className="kpi-value" style={{ color: 'var(--pos)' }}>{fmtEUR(totalIncome)}</div>
          <div className="kpi-meta">{filtered.filter(t => t.type === 'einnahme').length} Buchungen</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Ausgaben</div>
          <div className="kpi-value" style={{ color: 'var(--neg)' }}>{fmtEUR(totalExpense)}</div>
          <div className="kpi-meta">{filtered.filter(t => t.type === 'ausgabe').length} Buchungen</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Netto-Cashflow</div>
          <div className="kpi-value" style={{ color: totalNet >= 0 ? 'var(--pos)' : 'var(--neg)' }}>{fmtEUR(totalNet)}</div>
          <div className="kpi-meta">{totalIncome > 0 ? `Marge: ${((totalNet / totalIncome) * 100).toFixed(1)} %` : '—'}</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Buchungen</div>
          <div className="kpi-value">{txCount}</div>
          <div className="kpi-meta">{uncategorizedCount > 0 ? `${uncategorizedCount} ohne Kategorie` : 'alle kategorisiert'}</div>
        </div>
      </div>

      {/* Cashflow-Chart */}
      <div className="section" style={{ marginTop: 24 }}>
        <div className="section-header"><h2 className="section-title">Cashflow nach Monat</h2></div>
        <SmartBarChart months={months} />
      </div>

      {/* Transaktionen-Tabelle */}
      <div className="section">
        <div className="section-header">
          <h2 className="section-title">Buchungen</h2>
          <select className="form-input" style={{ maxWidth: 200 }} value={sortBy} onChange={e => setSortBy(e.target.value)}>
            <option value="date-desc">Neueste zuerst</option>
            <option value="date-asc">Älteste zuerst</option>
            <option value="amount-desc">Betrag absteigend</option>
            <option value="amount-asc">Betrag aufsteigend</option>
          </select>
        </div>
        {sorted.length === 0 ? (
          <div className="empty" style={{ padding: '40px 20px', textAlign: 'center' }}>
            <div className="empty-title">Keine Buchungen im Filter</div>
            <div style={{ color: 'var(--ink-3)' }}>Lockere Zeitraum, Objekt oder Suchbegriff.</div>
          </div>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Datum</th>
                  <th>Beschreibung</th>
                  <th>Empfänger</th>
                  <th>Kategorie</th>
                  <th>Objekt</th>
                  <th title="Verknüpfte Belege">📎</th>
                  <th className="num">Betrag</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {sorted.slice(0, 200).map(t => {
                  const prop = properties.find(p => p.id === t.propertyId);
                  const docCount = t.documentCount || 0;
                  return (
                    <tr key={t.id} style={{ cursor: 'pointer' }} onClick={() => { setEditingTx(t); setShowTxForm(true); }}>
                      <td className="muted" style={{ whiteSpace: 'nowrap' }}>{fmtDateShort(t.date)}</td>
                      <td className="strong" style={{ maxWidth: 280, overflow: 'hidden', textOverflow: 'ellipsis' }}>{t.description || '—'}</td>
                      <td className="muted">{t.counterparty || '—'}</td>
                      <td>{t.category ? <Pill>{t.category}</Pill> : <span className="muted" style={{ fontSize: 11.5 }}>—</span>}</td>
                      <td className="muted">{prop ? prop.name : '—'}</td>
                      <td title={docCount > 0 ? `${docCount} Beleg(e) verknüpft` : 'Kein Beleg verknüpft'} style={{ textAlign: 'center', color: docCount > 0 ? 'var(--accent)' : 'var(--ink-5)' }}>
                        {docCount > 0 ? `📎 ${docCount}` : '—'}
                      </td>
                      <td className="num strong" style={{ color: t.amount >= 0 ? 'var(--pos)' : 'var(--neg)', whiteSpace: 'nowrap' }}>
                        {t.amount >= 0 ? '+' : ''}{fmtEUR(t.amount)}
                      </td>
                      <td onClick={e => e.stopPropagation()} style={{ whiteSpace: 'nowrap' }}>
                        <button className="btn-link" onClick={() => { setEditingTx(t); setShowTxForm(true); }} title="Bearbeiten / Beleg verknüpfen">✎</button>
                        <button className="btn-link" style={{ marginLeft: 8, color: 'var(--neg)' }} onClick={() => setDeletingTx(t)} title="Löschen">✕</button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
            {sorted.length > 200 && (
              <div style={{ textAlign: 'center', color: 'var(--ink-3)', fontSize: 12, padding: '10px 0' }}>
                Zeige erste 200 von {sorted.length} Buchungen — engere Filter setzen für vollständige Übersicht oder CSV exportieren.
              </div>
            )}
          </div>
        )}
      </div>

      {/* Pro-Objekt + Kategorien */}
      <div className="two-col">
        <div className="section">
          <div className="section-header"><h2 className="section-title">Auswertung pro Objekt</h2></div>
          {propRows.length === 0 ? (
            <div className="empty" style={{ padding: 16 }}>Keine Objekt-Daten im Zeitraum.</div>
          ) : (
            <div>
              {propRows.map(p => (
                <div key={p.id} className="bar-row">
                  <div style={{ minWidth: 140 }}>
                    <div className="strong">{p.name}</div>
                    <div className="muted" style={{ fontSize: 11.5 }}>
                      Netto: <span style={{ color: p.net >= 0 ? 'var(--pos)' : 'var(--neg)' }}>{fmtEUR(p.net)}</span>
                      {p.grossYield > 0 && ` · ${p.grossYield.toFixed(2)} %`}
                    </div>
                  </div>
                  <div className="bar-track"><div className="bar-fill" style={{ width: `${(p.income / maxPropIncome) * 100}%` }}></div></div>
                  <div className="num strong">{fmtEUR(p.income)}</div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="section">
          <div className="section-header"><h2 className="section-title">Ausgaben nach Kategorie</h2></div>
          {catRows.length === 0 ? (
            <div className="empty" style={{ padding: 16 }}>Keine Ausgaben im Zeitraum.</div>
          ) : (
            <div>
              {catRows.map(([cat, amt]) => (
                <div key={cat} className="bar-row">
                  <div className="strong" style={{ minWidth: 140 }}>{cat}</div>
                  <div className="bar-track"><div className="bar-fill" style={{ width: `${(amt / maxCat) * 100}%`, background: 'var(--ink-3)' }}></div></div>
                  <div className="num strong">{fmtEUR(amt)}</div>
                </div>
              ))}
              <div style={{ paddingTop: 12, marginTop: 8, borderTop: '1px solid var(--line-2)', display: 'flex', justifyContent: 'space-between' }}>
                <span className="strong">Summe</span>
                <span className="num strong">{fmtEUR(totalExpense)}</span>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { TenantsPage, TenantDetail, CalendarPage, MaintenancePage, ReportsPage });
