import { useState, type ReactNode } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { formatINR } from '@sims/domain'
import { Badge, DataTable, EmptyState, ErrorState, Notice, PageHeader, Skeleton, StatCard, Stats } from '@sims/ui'
import { getDashboard, isManagerial } from '../api'
import { QueueActions, RULE_LABEL, reminderTone } from '../components/ReminderQueue'
import { useData } from './Clients'

const inr = (p: number) => formatINR(p)

/** Dashboard home — today's money + the manual reminder queue (spec §3). */
export function Dashboard() {
  const nav = useNavigate()
  // My Day (D18 WS-E): owner/manager toggle Mine ↔ Everyone; staff are always
  // scoped to their own book server-side, so they get no toggle.
  const managerial = isManagerial()
  const [mine, setMine] = useState(false)
  const dash = useData(() => getDashboard(mine), [mine])
  const [err, setErr] = useState('')
  const v = dash.data

  return (
    <div className="wf-page">
      <PageHeader
        title={managerial && mine ? 'My Day' : 'Dashboard'}
        desc="Today’s money — dues, renewals, follow-ups, and the reminder queue."
        {...(managerial ? {
          actions: (
            <span style={{ display: 'flex', gap: 4 }}>
              <button type="button" className={`wf${!mine ? ' active' : ''}`} onClick={() => setMine(false)}>Everyone</button>
              <button type="button" className={`wf${mine ? ' active' : ''}`} onClick={() => setMine(true)}>Mine</button>
            </span>
          ),
        } : {})}
      />
      {dash.error !== undefined && <ErrorState message={dash.error} onRetry={dash.reload} />}
      {err !== '' && <Notice tone="err">{err}</Notice>}
      {v === undefined && dash.error === undefined ? <Skeleton rows={5} /> : v === undefined ? null : (
        <>
          <Stats>
            <StatCard label="Overdue" value={inr(v.totals.overduePaise)} hint={`${v.overdue.length} invoice(s)`} />
            <StatCard label="Queued reminders" value={String(v.totals.queued)} />
            <StatCard label="Failed sends" value={String(v.totals.failed)} {...(v.totals.failed > 0 ? { hint: 'needs attention', hintTone: 'err' as const } : {})} />
            <StatCard label="Follow-ups today" value={String(v.followUpsToday.length)} />
          </Stats>

          <h3 style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
            Reminder queue
            <Link to="/reminders" style={{ fontSize: 13, fontWeight: 500 }}>View all →</Link>
          </h3>
          {v.queue.length === 0 ? <EmptyState>Nothing waiting — all clear.</EmptyState> : (
            <DataTable
              columns={[
                { key: 'kind', label: 'Kind' }, { key: 'client', label: 'Client' },
                { key: 'ref', label: 'Reference' }, { key: 'status', label: 'Status' },
                { key: 'error', label: 'Error' }, { key: 'act', label: '' },
              ]}
              rowTone={(i) => {
                const s = v.queue[i]?.status
                return s === 'failed' ? 'err' : undefined
              }}
              rows={v.queue.map((rem) => ({
                kind: rem.label !== '' ? rem.label : RULE_LABEL[rem.ruleKind] ?? rem.ruleKind,
                client: rem.clientName,
                ref: rem.docNo ?? rem.duePeriod,
                status: <Badge tone={reminderTone(rem.status)}>{rem.status}</Badge>,
                error: rem.error ?? '—',
                act: <QueueActions rem={rem} onDone={dash.reload} onError={setErr} />,
              }))}
            />
          )}
          {v.queueTotal > v.queue.length && (
            // No silent caps (rule 8): the table is the first page only — say so.
            <p style={{ marginTop: 6, fontSize: 13, color: 'var(--text-muted, #666)' }}>
              Showing {v.queue.length} of {v.queueTotal} — <Link to="/reminders">see the full queue</Link>.
            </p>
          )}

          <Section title="Overdue" empty="No overdue invoices." rows={v.overdue}
            columns={[{ key: 'no', label: 'Invoice' }, { key: 'client', label: 'Client' }, { key: 'days', label: 'Days', numeric: true }, { key: 'due', label: 'Outstanding', numeric: true }]}
            onRowClick={(i) => nav(`/documents/${v.overdue[i]!.docId}`)}
            map={(o) => ({ no: o.docNo ?? '—', client: o.clientName, days: o.daysOverdue, due: inr(o.outstandingPaise) })} />

          <div className="dash-grid">
            <section>
              <Section title="Due this week" empty="No recurring bills due this week." rows={v.dueThisWeek}
                columns={[{ key: 'client', label: 'Client' }, { key: 'on', label: 'Runs on' }, { key: 'amt', label: 'Amount', numeric: true }]}
                map={(d) => ({ client: d.clientName, on: d.nextRun, amt: d.amountPaise !== null ? inr(d.amountPaise) : 'from price book' })} />
            </section>

            <section>
              <Section title="Renewals this month" empty="No renewals this month." rows={v.renewalsThisMonth}
                columns={[{ key: 'client', label: 'Client' }, { key: 'on', label: 'Renews on' }]}
                onRowClick={(i) => nav(`/clients/${v.renewalsThisMonth[i]!.clientId}`)}
                map={(r) => ({ client: r.clientName, on: r.nextRenewal })} />
            </section>

            <section>
              <Section title="Follow-ups today" empty="No follow-ups due." rows={v.followUpsToday}
                columns={[{ key: 'client', label: 'Client' }, { key: 'on', label: 'Due' }, { key: 'notes', label: 'Notes' }]}
                onRowClick={(i) => nav(`/clients/${v.followUpsToday[i]!.clientId}`)}
                map={(f) => ({ client: f.clientName, on: f.followUpOn, notes: f.notes !== '' ? f.notes : '—' })} />
            </section>

            <section>
              <Section title="Recent payments" empty="No payments recorded yet." rows={v.recentPayments}
                columns={[{ key: 'client', label: 'Client' }, { key: 'on', label: 'Received' }, { key: 'mode', label: 'Mode' }, { key: 'amt', label: 'Amount', numeric: true }]}
                map={(p) => ({ client: p.clientName, on: p.receivedOn, mode: p.mode, amt: inr(p.amountPaise) })} />
            </section>
          </div>
        </>
      )}
    </div>
  )
}

/** A titled table with an empty state — keeps the dashboard body declarative. */
function Section<T>(props: {
  title: string; empty: string; rows: T[]
  columns: { key: string; label: string; numeric?: boolean }[]
  map: (row: T) => Record<string, ReactNode>; onRowClick?: (i: number) => void
}) {
  return (
    <>
      <h3 style={{ marginTop: 20 }}>{props.title}</h3>
      {props.rows.length === 0 ? <EmptyState>{props.empty}</EmptyState> : (
        <DataTable
          columns={props.columns}
          {...(props.onRowClick !== undefined ? { onRowClick: (_r: unknown, i: number) => props.onRowClick!(i) } : {})}
          rows={props.rows.map(props.map)}
        />
      )}
    </>
  )
}

