import { useState, useEffect } from 'react'
import { api } from '../api'
import { PageHeader, Card, Btn, StatusBadge } from '../components/Layout'
import { fmtGBP } from '../types'

interface SalesCol { gl_code: string; category: string; net_amount: number; vat_amount: number; gross_amount: number }
interface ReconRow { category: string; banked_amount: number; reported_amount: number }
interface DayData {
  date: string
  cash_up: { id: number; status: 'draft' | 'final'; total_cash_counted: string } | null
  reconciliation: ReconRow[]
  daily_stats: { gross_sales: number; transaction_count: number } | null
  sales_breakdown: SalesCol[]
}

// Newbook occupancy_data: per-category with per-date occupancy map
interface OccupancyCategoryRaw {
  category_id?: string | number
  category_name?: string
  occupancy?: Record<string, { occupied?: number; maintenance?: number; available?: number }>
  // fallback flat format
  period?: string; date?: string; rooms_sold?: number; total_rooms?: number; total_people?: number
}

interface BookingRaw {
  booking_arrival?: string
  booking_departure?: string
  booking_adults?: string | number
  booking_children?: string | number
  booking_infants?: string | number
  category_id?: string | number
  category_name?: string
  booking_placed?: string
  tariffs_quoted?: Array<{ stay_date?: string; calculated_amount?: string | number }>
}

interface SiteRaw {
  category_id?: string | number
  category_name?: string
}

interface EarnedRevenueItem {
  period?: string
  gl_group_id?: string
  earned_revenue_ex?: number
  earned_revenue_tax?: number
  earned_revenue?: number
}

interface ReportResult {
  report_data: DayData[]
  sales_columns: Array<{ gl_code: string; display_name: string }>
  occupancy_data: OccupancyCategoryRaw[]
  bookings_data: BookingRaw[]
  sites_data: SiteRaw[]
  earned_revenue: EarnedRevenueItem[]
  gl_accounts: Array<{ gl_group_id?: string; gl_group_name?: string }>
}

interface DebtorBalance { creditors: number; debtors: number; overall: number }
interface DebtorsResult {
  period_open_balance: DebtorBalance
  balances_by_date: Record<string, DebtorBalance>
}

interface DayOccStats {
  roomsOccupied: number
  people: number; adults: number; children: number; infants: number
  netAccom: number
  ggr: number; ggrRoomCount: number
  avgLeadTime: number; arrivingCount: number
}

const RECON_LABELS: Record<string, string> = {
  cash: 'Cash',
  gateway_visa_mc: 'Gateway V/MC',
  gateway_amex: 'Gateway Amex',
  pdq_visa_mc: 'PDQ V/MC',
  pdq_amex: 'PDQ Amex',
  bacs: 'BACS',
}
const VARIANCE_CATEGORIES = new Set(['cash', 'pdq_visa_mc', 'pdq_amex'])

function fmtDate(d: string) {
  const s = (d ?? '').slice(0, 10)
  if (!s) return '—'
  return new Date(s + 'T12:00:00').toLocaleDateString('en-GB', { weekday: 'short', day: '2-digit', month: 'short' })
}

function buildOccupancyStats(
  dates: string[],
  occupancyData: OccupancyCategoryRaw[],
  bookingsData: BookingRaw[],
  sitesData: SiteRaw[],
  earnedRevenue: EarnedRevenueItem[],
  glAccounts: Array<{ gl_group_id?: string; gl_group_name?: string }>,
): { byDate: Record<string, DayOccStats>; totalRooms: number } {

  // Total rooms (exclude overflow)
  const totalRooms = sitesData.filter(s =>
    !(s.category_name ?? '').toLowerCase().includes('overflow')
  ).length

  // Rooms occupied by date from per-category occupancy data
  const roomsByDate: Record<string, number> = {}
  for (const cat of occupancyData) {
    if ((cat.category_name ?? '').toLowerCase().includes('overflow')) continue
    if (cat.occupancy && typeof cat.occupancy === 'object') {
      for (const [date, occ] of Object.entries(cat.occupancy)) {
        const d = date.slice(0, 10)
        roomsByDate[d] = (roomsByDate[d] ?? 0) + (Number(occ?.occupied) || 0)
      }
    }
  }

  // Net accommodation revenue by date (identify ACC group from GL accounts)
  const accomGroupIds = new Set<string>()
  for (const a of glAccounts) {
    const name = (a.gl_group_name ?? '').toLowerCase()
    if (name.startsWith('acc') || name.includes('accommodation')) {
      if (a.gl_group_id) accomGroupIds.add(a.gl_group_id)
    }
  }
  const accomByDate: Record<string, number> = {}
  for (const item of earnedRevenue) {
    const d = (item.period ?? '').slice(0, 10)
    if (!d || !item.gl_group_id) continue
    if (accomGroupIds.has(item.gl_group_id)) {
      accomByDate[d] = (accomByDate[d] ?? 0) + (item.earned_revenue_ex ?? 0)
    }
  }

  // Per-day stats from bookings
  const bookingStats: Record<string, {
    people: number; adults: number; children: number; infants: number
    totalRate: number; rateRooms: number; leadDaysSum: number; arrivingCount: number
  }> = {}

  for (const b of bookingsData) {
    const catName = (b.category_name ?? '').toLowerCase()
    if (catName.includes('overflow')) continue

    const arrival = (b.booking_arrival ?? '').slice(0, 10)
    const departure = (b.booking_departure ?? '').slice(0, 10)
    if (!arrival || !departure) continue

    const adults = Number(b.booking_adults) || 0
    const children = Number(b.booking_children) || 0
    const infants = Number(b.booking_infants) || 0
    const people = adults + children + infants

    const placedStr = (b.booking_placed ?? '').slice(0, 10)
    let leadDays = 0
    if (placedStr) {
      const placedMs = new Date(placedStr + 'T12:00:00').getTime()
      const arrivalMs = new Date(arrival + 'T12:00:00').getTime()
      leadDays = Math.max(0, Math.floor((arrivalMs - placedMs) / 86400000))
    }

    // Build tariff lookup: { stayDate → amount }
    const tariffMap: Record<string, number> = {}
    for (const t of (b.tariffs_quoted ?? [])) {
      const td = (t.stay_date ?? '').slice(0, 10)
      if (td) tariffMap[td] = (tariffMap[td] ?? 0) + (Number(t.calculated_amount) || 0)
    }

    // Iterate each stay day
    let cur = new Date(arrival + 'T12:00:00')
    const dep = new Date(departure + 'T12:00:00')
    while (cur < dep) {
      const d = cur.toISOString().slice(0, 10)
      if (!bookingStats[d]) bookingStats[d] = { people: 0, adults: 0, children: 0, infants: 0, totalRate: 0, rateRooms: 0, leadDaysSum: 0, arrivingCount: 0 }
      const s = bookingStats[d]
      s.people += people; s.adults += adults; s.children += children; s.infants += infants
      if (tariffMap[d] != null) { s.totalRate += tariffMap[d]; s.rateRooms++ }
      if (d === arrival) { s.leadDaysSum += leadDays; s.arrivingCount++ }
      cur.setDate(cur.getDate() + 1)
    }
  }

  const byDate: Record<string, DayOccStats> = {}
  for (const date of dates) {
    const bk = bookingStats[date]
    const roomsOccupied = roomsByDate[date] ?? 0
    const netAccom = accomByDate[date] ?? 0
    byDate[date] = {
      roomsOccupied,
      people:   bk?.people   ?? 0,
      adults:   bk?.adults   ?? 0,
      children: bk?.children ?? 0,
      infants:  bk?.infants  ?? 0,
      netAccom,
      ggr:         bk && bk.rateRooms > 0 ? bk.totalRate / bk.rateRooms : 0,
      ggrRoomCount: bk?.rateRooms ?? 0,
      avgLeadTime:  bk && bk.arrivingCount > 0 ? Math.round(bk.leadDaysSum / bk.arrivingCount) : 0,
      arrivingCount: bk?.arrivingCount ?? 0,
    }
  }
  return { byDate, totalRooms }
}

export function MultiDayReport() {
  const [startDate, setStartDate] = useState(() => {
    const d = new Date(); d.setDate(d.getDate() - 6); return d.toISOString().slice(0, 10)
  })
  const [numDays, setNumDays] = useState(7)
  const [result, setResult] = useState<ReportResult | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [debtors, setDebtors] = useState<DebtorsResult | null>(null)
  const [debtorsLoading, setDebtorsLoading] = useState(false)

  async function generate() {
    setLoading(true); setError(''); setResult(null); setDebtors(null)
    try {
      const data = await api.post<ReportResult>('/reports/multiday', { start_date: startDate, num_days: numDays })
      setResult(data)
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Failed to generate report')
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    if (!result) return
    setDebtorsLoading(true)
    api.post<DebtorsResult>('/reports/debtors-creditors', { start_date: startDate, num_days: numDays })
      .then(d => setDebtors(d))
      .catch(() => {})
      .finally(() => setDebtorsLoading(false))
  }, [result, startDate, numDays])

  const dates = result?.report_data.map(d => d.date) ?? []
  const salesCols = result?.sales_columns ?? []

  const occStats = result ? buildOccupancyStats(
    dates,
    result.occupancy_data,
    result.bookings_data,
    result.sites_data,
    result.earned_revenue ?? [],
    result.gl_accounts ?? [],
  ) : null

  return (
    <div style={{ padding: '1.5rem' }}>
      <PageHeader title="Weekly / Multi-Day Report" />

      {/* Controls */}
      <Card style={{ marginBottom: '1.5rem', display: 'flex', gap: '1rem', alignItems: 'flex-end', flexWrap: 'wrap' }}>
        <div>
          <label style={labelSt}>Start Date</label>
          <input type="date" value={startDate} onChange={e => setStartDate(e.target.value)} style={inpSt} />
        </div>
        <div>
          <label style={labelSt}>Number of Days</label>
          <input type="number" value={numDays} min={1} max={365}
            onChange={e => setNumDays(Math.max(1, Math.min(365, parseInt(e.target.value) || 7)))}
            style={{ ...inpSt, width: '80px' }} />
        </div>
        <Btn onClick={generate} disabled={loading}>
          {loading ? 'Generating…' : 'Generate Report'}
        </Btn>
      </Card>

      {error && (
        <div style={{ background: '#fee2e2', color: 'var(--danger)', border: '1px solid #fecaca', borderRadius: '6px', padding: '0.75rem 1rem', marginBottom: '1rem' }}>
          {error}
        </div>
      )}

      {result && (
        <>
          {/* Daily Status Row */}
          <Card style={{ marginBottom: '1.5rem' }}>
            <h2 style={sectionTitle}>Daily Cash Up Status</h2>
            <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
              {result.report_data.map(day => (
                <div key={day.date} style={{
                  textAlign: 'center', padding: '0.75rem 1rem',
                  background: 'var(--body-bg)', borderRadius: '6px',
                  border: '1px solid var(--card-border)', minWidth: '80px',
                }}>
                  <div style={{ fontSize: '0.75rem', color: 'var(--text-mid)', marginBottom: '0.375rem' }}>{fmtDate(day.date)}</div>
                  {day.cash_up
                    ? <StatusBadge status={day.cash_up.status} />
                    : <span style={{ fontSize: '0.7rem', color: 'var(--text-mid)', fontWeight: 600, textTransform: 'uppercase', background: 'var(--card-border)', padding: '0.2rem 0.5rem', borderRadius: '4px' }}>None</span>
                  }
                  {day.cash_up && (
                    <div style={{ fontSize: '0.8rem', fontWeight: 700, marginTop: '0.375rem' }}>
                      {fmtGBP(day.cash_up.total_cash_counted)}
                    </div>
                  )}
                </div>
              ))}
            </div>
          </Card>

          {/* Table 1: Reconciliation */}
          <Card style={{ marginBottom: '1.5rem', overflowX: 'auto' }}>
            <h2 style={sectionTitle}>Payment Reconciliation</h2>
            <table style={{ borderCollapse: 'collapse', fontSize: '0.8rem', minWidth: '600px', width: '100%' }}>
              <thead>
                <tr style={{ borderBottom: '2px solid var(--card-border)' }}>
                  <th style={{ ...th, textAlign: 'left' }}>Category</th>
                  {dates.map(d => <th key={d} style={th}>{fmtDate(d)}</th>)}
                  <th style={th}>Total</th>
                </tr>
              </thead>
              <tbody>
                {Object.entries(RECON_LABELS).map(([key, label]) => {
                  const rows = result.report_data.map(day => day.reconciliation.find(r => r.category === key))
                  const bankedVals = rows.map(r => r?.banked_amount ?? 0)
                  const reportedVals = rows.map(r => r?.reported_amount ?? 0)
                  const hasVariance = VARIANCE_CATEGORIES.has(key)
                  const totalBanked = bankedVals.reduce((s, v) => s + v, 0)
                  const totalReported = reportedVals.reduce((s, v) => s + v, 0)
                  if (bankedVals.every(v => v === 0) && reportedVals.every(v => v === 0)) return null
                  return [
                    hasVariance && (
                      <tr key={`${key}-rep`} style={{ borderBottom: '1px solid transparent' }}>
                        <td style={{ ...td, paddingLeft: '0.5rem', color: 'var(--text-mid)', fontSize: '0.75rem' }}>{label} — Newbook</td>
                        {reportedVals.map((v, i) => (
                          <td key={i} style={{ ...td, textAlign: 'right', color: 'var(--text-mid)', fontSize: '0.75rem' }}>{v ? fmtGBP(v) : '—'}</td>
                        ))}
                        <td style={{ ...td, textAlign: 'right', color: 'var(--text-mid)', fontSize: '0.75rem' }}>{fmtGBP(totalReported)}</td>
                      </tr>
                    ),
                    <tr key={`${key}-bnk`} style={{ borderBottom: '1px solid var(--card-border)' }}>
                      <td style={{ ...td, fontWeight: 600 }}>{hasVariance ? `${label} — Banked` : label}</td>
                      {bankedVals.map((v, i) => {
                        const rep = reportedVals[i]
                        const vari = hasVariance ? (v - rep) : null
                        return (
                          <td key={i} style={{ ...td, textAlign: 'right' }}>
                            {v ? fmtGBP(v) : '—'}
                            {vari !== null && Math.abs(vari) > 0.005 && (
                              <div style={{ fontSize: '0.7rem', color: vari < 0 ? 'var(--danger)' : '#16a34a' }}>
                                {vari > 0 ? '+' : ''}{fmtGBP(vari)}
                              </div>
                            )}
                          </td>
                        )
                      })}
                      <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>
                        {fmtGBP(totalBanked)}
                        {hasVariance && Math.abs(totalBanked - totalReported) > 0.005 && (
                          <div style={{ fontSize: '0.7rem', color: totalBanked - totalReported < 0 ? 'var(--danger)' : '#16a34a' }}>
                            {totalBanked - totalReported > 0 ? '+' : ''}{fmtGBP(totalBanked - totalReported)}
                          </div>
                        )}
                      </td>
                    </tr>,
                  ].filter(Boolean)
                })}
                <tr style={{ borderTop: '2px solid var(--card-border)', background: 'var(--body-bg)' }}>
                  <td style={{ ...td, fontWeight: 700 }}>Total</td>
                  {result.report_data.map((day, i) => {
                    const t = day.reconciliation.reduce((s, r) => s + r.banked_amount, 0)
                    return <td key={i} style={{ ...td, textAlign: 'right', fontWeight: 700 }}>{t ? fmtGBP(t) : '—'}</td>
                  })}
                  <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>
                    {fmtGBP(result.report_data.reduce((s, d) => s + d.reconciliation.reduce((ss, r) => ss + r.banked_amount, 0), 0))}
                  </td>
                </tr>
              </tbody>
            </table>
          </Card>

          {/* Table 2: Sales Breakdown */}
          {salesCols.length > 0 && (
            <Card style={{ marginBottom: '1.5rem', overflowX: 'auto' }}>
              <h2 style={sectionTitle}>Sales Breakdown</h2>
              <table style={{ borderCollapse: 'collapse', fontSize: '0.8rem', minWidth: '600px', width: '100%' }}>
                <thead>
                  <tr style={{ borderBottom: '2px solid var(--card-border)' }}>
                    <th style={{ ...th, textAlign: 'left' }}>Category</th>
                    {dates.map(d => <th key={d} style={th}>{fmtDate(d)}</th>)}
                    <th style={th}>Total Net</th>
                    <th style={th}>Total VAT</th>
                    <th style={th}>Total Gross</th>
                  </tr>
                </thead>
                <tbody>
                  {salesCols.map(col => {
                    const vals = result.report_data.map(day => {
                      const sb = day.sales_breakdown.find(s => s.gl_code === col.gl_code)
                      return { net: sb?.net_amount ?? 0, gross: sb?.gross_amount ?? 0, vat: sb?.vat_amount ?? 0 }
                    })
                    const totNet = vals.reduce((s, v) => s + v.net, 0)
                    const totVat = vals.reduce((s, v) => s + v.vat, 0)
                    const totGross = vals.reduce((s, v) => s + v.gross, 0)
                    if (vals.every(v => v.gross === 0 && v.net === 0)) return null
                    return (
                      <tr key={col.gl_code} style={{ borderBottom: '1px solid var(--card-border)' }}>
                        <td style={td}>{col.display_name}</td>
                        {vals.map((v, i) => (
                          <td key={i} style={{ ...td, textAlign: 'right' }}>
                            {v.gross ? fmtGBP(v.gross) : '—'}
                            {v.vat > 0 && <div style={{ fontSize: '0.7rem', color: 'var(--text-mid)' }}>net {fmtGBP(v.net)}</div>}
                          </td>
                        ))}
                        <td style={{ ...td, textAlign: 'right' }}>{fmtGBP(totNet)}</td>
                        <td style={{ ...td, textAlign: 'right', color: 'var(--text-mid)' }}>{fmtGBP(totVat)}</td>
                        <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>{fmtGBP(totGross)}</td>
                      </tr>
                    )
                  })}
                  <tr style={{ borderTop: '2px solid var(--card-border)', background: 'var(--body-bg)', fontWeight: 700 }}>
                    <td style={td}>TOTAL</td>
                    {result.report_data.map((day, i) => {
                      const g = day.sales_breakdown.reduce((s, sb) => s + (sb.gross_amount ?? 0), 0)
                      const n = day.sales_breakdown.reduce((s, sb) => s + (sb.net_amount ?? 0), 0)
                      return (
                        <td key={i} style={{ ...td, textAlign: 'right' }}>
                          {g ? fmtGBP(g) : '—'}
                          {n > 0 && <div style={{ fontSize: '0.7rem', color: 'var(--text-mid)' }}>net {fmtGBP(n)}</div>}
                        </td>
                      )
                    })}
                    <td style={{ ...td, textAlign: 'right' }}>
                      {fmtGBP(result.report_data.reduce((s, d) => s + d.sales_breakdown.reduce((ss, sb) => ss + (sb.net_amount ?? 0), 0), 0))}
                    </td>
                    <td style={{ ...td, textAlign: 'right', color: 'var(--text-mid)' }}>
                      {fmtGBP(result.report_data.reduce((s, d) => s + d.sales_breakdown.reduce((ss, sb) => ss + (sb.vat_amount ?? 0), 0), 0))}
                    </td>
                    <td style={{ ...td, textAlign: 'right' }}>
                      {fmtGBP(result.report_data.reduce((s, d) => s + d.sales_breakdown.reduce((ss, sb) => ss + (sb.gross_amount ?? 0), 0), 0))}
                    </td>
                  </tr>
                </tbody>
              </table>
            </Card>
          )}

          {/* Table 3: Occupancy */}
          {occStats && (
            <Card style={{ marginBottom: '1.5rem', overflowX: 'auto' }}>
              <h2 style={sectionTitle}>Occupancy</h2>
              {occStats.totalRooms > 0 && (
                <p style={{ fontSize: '0.8rem', color: 'var(--text-mid)', marginBottom: '0.75rem' }}>
                  Total rooms: {occStats.totalRooms}
                </p>
              )}
              <table style={{ borderCollapse: 'collapse', fontSize: '0.8rem', minWidth: '600px', width: '100%' }}>
                <thead>
                  <tr style={{ borderBottom: '2px solid var(--card-border)' }}>
                    <th style={{ ...th, textAlign: 'left' }}>Metric</th>
                    {dates.map(d => <th key={d} style={th}>{fmtDate(d)}</th>)}
                    <th style={th}>Total / Avg</th>
                  </tr>
                </thead>
                <tbody>
                  {[
                    {
                      label: 'Rooms Occupied',
                      vals: dates.map(d => occStats.byDate[d]?.roomsOccupied ?? 0),
                      fmt: (v: number) => String(v),
                      total: (vs: number[]) => String(vs.reduce((s, v) => s + v, 0)),
                    },
                    {
                      label: 'Occ %',
                      vals: dates.map(d => occStats.totalRooms > 0 ? (occStats.byDate[d]?.roomsOccupied ?? 0) / occStats.totalRooms * 100 : 0),
                      fmt: (v: number) => v ? v.toFixed(1) + '%' : '—',
                      total: (vs: number[]) => { const avg = vs.filter(v => v > 0); return avg.length ? (avg.reduce((s, v) => s + v, 0) / avg.length).toFixed(1) + '% avg' : '—' },
                    },
                    {
                      label: 'Guests',
                      vals: dates.map(d => occStats.byDate[d]?.people ?? 0),
                      fmt: (v: number) => v ? String(v) : '—',
                      total: (vs: number[]) => String(vs.reduce((s, v) => s + v, 0)),
                    },
                    {
                      label: 'Net Accom',
                      vals: dates.map(d => occStats.byDate[d]?.netAccom ?? 0),
                      fmt: (v: number) => v ? fmtGBP(v) : '—',
                      total: (vs: number[]) => fmtGBP(vs.reduce((s, v) => s + v, 0)),
                    },
                    {
                      label: 'Avg Net / Room',
                      vals: dates.map(d => {
                        const s = occStats.byDate[d]; if (!s) return 0
                        return s.roomsOccupied > 0 ? s.netAccom / s.roomsOccupied : 0
                      }),
                      fmt: (v: number) => v ? fmtGBP(v) : '—',
                      total: (vs: number[]) => {
                        const totalNetAccom = dates.reduce((s, d) => s + (occStats.byDate[d]?.netAccom ?? 0), 0)
                        const totalRooms = dates.reduce((s, d) => s + (occStats.byDate[d]?.roomsOccupied ?? 0), 0)
                        return totalRooms > 0 ? fmtGBP(totalNetAccom / totalRooms) + ' avg' : '—'
                      },
                    },
                    {
                      label: 'REVPAR',
                      vals: dates.map(d => {
                        if (!occStats.totalRooms) return 0
                        return (occStats.byDate[d]?.netAccom ?? 0) / occStats.totalRooms
                      }),
                      fmt: (v: number) => v ? fmtGBP(v) : '—',
                      total: (vs: number[]) => {
                        const avg = vs.filter(v => v > 0)
                        return avg.length ? fmtGBP(avg.reduce((s, v) => s + v, 0) / avg.length) + ' avg' : '—'
                      },
                    },
                    {
                      label: 'GGR (Avg Rate)',
                      vals: dates.map(d => occStats.byDate[d]?.ggr ?? 0),
                      fmt: (v: number) => v ? fmtGBP(v) : '—',
                      total: (vs: number[]) => {
                        const active = vs.filter(v => v > 0)
                        return active.length ? fmtGBP(active.reduce((s, v) => s + v, 0) / active.length) + ' avg' : '—'
                      },
                    },
                    {
                      label: 'Avg Lead Time',
                      vals: dates.map(d => occStats.byDate[d]?.avgLeadTime ?? 0),
                      fmt: (v: number, i: number) => {
                        const s = occStats.byDate[dates[i]]
                        if (!s || !s.arrivingCount) return '—'
                        return v + ' days'
                      },
                      total: (vs: number[]) => {
                        const active = vs.filter(v => v > 0)
                        return active.length ? Math.round(active.reduce((s, v) => s + v, 0) / active.length) + ' days avg' : '—'
                      },
                    },
                  ].map(row => (
                    <tr key={row.label} style={{ borderBottom: '1px solid var(--card-border)' }}>
                      <td style={{ ...td, fontWeight: 600 }}>{row.label}</td>
                      {row.vals.map((v, i) => (
                        <td key={i} style={{ ...td, textAlign: 'right' }}>{row.fmt(v, i)}</td>
                      ))}
                      <td style={{ ...td, textAlign: 'right', fontWeight: 600, color: 'var(--text-mid)' }}>
                        {row.total(row.vals)}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </Card>
          )}

          {/* Table 4: Debtors / Creditors */}
          <Card style={{ marginBottom: '1.5rem', overflowX: 'auto' }}>
            <h2 style={sectionTitle}>Debtors / Creditors</h2>
            {debtorsLoading ? (
              <p style={{ color: 'var(--text-mid)', fontSize: '0.875rem' }}>Loading balances…</p>
            ) : debtors ? (
              <table style={{ borderCollapse: 'collapse', fontSize: '0.8rem', minWidth: '400px', width: '100%' }}>
                <thead>
                  <tr style={{ borderBottom: '2px solid var(--card-border)' }}>
                    <th style={{ ...th, textAlign: 'left' }}>Date</th>
                    <th style={th}>Debtors</th>
                    <th style={th}>Creditors</th>
                    <th style={th}>Net</th>
                  </tr>
                </thead>
                <tbody>
                  <tr style={{ borderBottom: '1px solid var(--card-border)', background: 'var(--body-bg)' }}>
                    <td style={{ ...td, fontWeight: 600, color: 'var(--text-mid)' }}>Opening Balance</td>
                    <td style={{ ...td, textAlign: 'right' }}>{fmtGBP(debtors.period_open_balance.debtors)}</td>
                    <td style={{ ...td, textAlign: 'right' }}>{fmtGBP(debtors.period_open_balance.creditors)}</td>
                    <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>{fmtGBP(debtors.period_open_balance.overall)}</td>
                  </tr>
                  {dates.map(d => {
                    const b = debtors.balances_by_date[d]
                    if (!b) return null
                    return (
                      <tr key={d} style={{ borderBottom: '1px solid var(--card-border)' }}>
                        <td style={td}>{fmtDate(d)}</td>
                        <td style={{ ...td, textAlign: 'right' }}>{fmtGBP(b.debtors)}</td>
                        <td style={{ ...td, textAlign: 'right' }}>{fmtGBP(b.creditors)}</td>
                        <td style={{ ...td, textAlign: 'right', fontWeight: 700, color: b.overall >= 0 ? '#16a34a' : 'var(--danger)' }}>
                          {fmtGBP(b.overall)}
                        </td>
                      </tr>
                    )
                  })}
                  {(() => {
                    const last = debtors.balances_by_date[dates[dates.length - 1]]
                    if (!last) return null
                    return (
                      <tr style={{ borderTop: '2px solid var(--card-border)', background: 'var(--body-bg)' }}>
                        <td style={{ ...td, fontWeight: 700 }}>Period Close</td>
                        <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>{fmtGBP(last.debtors)}</td>
                        <td style={{ ...td, textAlign: 'right', fontWeight: 700 }}>{fmtGBP(last.creditors)}</td>
                        <td style={{ ...td, textAlign: 'right', fontWeight: 700, color: last.overall >= 0 ? '#16a34a' : 'var(--danger)' }}>
                          {fmtGBP(last.overall)}
                        </td>
                      </tr>
                    )
                  })()}
                </tbody>
              </table>
            ) : (
              <p style={{ color: 'var(--text-mid)', fontSize: '0.875rem' }}>Balances unavailable.</p>
            )}
          </Card>
        </>
      )}
    </div>
  )
}

const labelSt: React.CSSProperties = { fontSize: '0.75rem', color: 'var(--text-mid)', display: 'block', marginBottom: '0.25rem' }
const inpSt: React.CSSProperties = { border: '1px solid var(--card-border)', borderRadius: '6px', padding: '0.4rem 0.6rem', fontSize: '0.875rem' }
const sectionTitle: React.CSSProperties = { fontSize: '1rem', fontWeight: 700, marginBottom: '1rem' }
const th: React.CSSProperties = { padding: '0.5rem 0.625rem', textAlign: 'right', color: 'var(--text-mid)', fontWeight: 600, whiteSpace: 'nowrap' }
const td: React.CSSProperties = { padding: '0.45rem 0.625rem' }
