import { useMemo, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import {
  Badge, Button, DataTable, EmptyState, ErrorState, FilterChips, Notice, PageHeader, Skeleton, Toolbar, useToast,
} from '@sims/ui'
import {
  getSmsBalances, generateModuleRenewalQuote, refreshSmsBalances, isManagerial, type SmsBalanceRow,
} from '../api'
import { useData } from './Clients'

type Scope = 'low' | 'all' | 'unknown'

/** "3h ago" / "2d ago" from an ISO timestamp — compact freshness for the Checked column. */
function ago(iso: string | null): string {
  if (iso === null) return 'never'
  const ms = Date.now() - Date.parse(iso)
  if (Number.isNaN(ms)) return '—'
  const mins = Math.floor(ms / 60000)
  if (mins < 1) return 'just now'
  if (mins < 60) return `${mins}m ago`
  const hrs = Math.floor(mins / 60)
  if (hrs < 24) return `${hrs}h ago`
  return `${Math.floor(hrs / 24)}d ago`
}

/**
 * SMS credit review (D28): every SMS client with its balance, lowest first, so the
 * ones about to run dry are at the top. "Low" (below the threshold) is the default
 * view — that's the upsell list. One click raises a top-up proforma; the client name
 * links to the Modules tab where the balance is recorded. Balances are entered by the
 * team (there is no SMS-gateway sync — deliberately kept simple).
 */
export function SmsBalances() {
  const nav = useNavigate()
  const toast = useToast()
  const [scope, setScope] = useState<Scope>('low')
  const [busy, setBusy] = useState<string | undefined>()
  const [refreshing, setRefreshing] = useState(false)
  const [showCreds, setShowCreds] = useState(true) // managerial: show username/password columns
  const list = useData(getSmsBalances, [])
  const managerial = isManagerial()

  /** Download the SMS logins as a CSV (managerial): client, code, username, password, provider, balance. */
  const downloadCreds = () => {
    const rows = data?.rows ?? []
    const esc = (v: string | number | null) => {
      const s = v === null ? '' : String(v)
      return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s
    }
    const header = ['Code', 'Client', 'Username', 'Password', 'Provider', 'Balance', 'Installation date', 'Phone']
    const lines = [header.join(',')]
    for (const r of rows) {
      lines.push([esc(r.clientCode), esc(r.clientName), esc(r.username), esc(r.password),
        esc(r.provider), esc(r.balance), esc(r.installationDate), esc(r.phone)].join(','))
    }
    const blob = new Blob([lines.join('\n')], { type: 'text/csv;charset=utf-8' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url; a.download = 'sms-credentials.csv'; a.click()
    URL.revokeObjectURL(url)
  }

  const refreshAll = () => {
    if (refreshing) return
    setRefreshing(true)
    refreshSmsBalances()
      .then((s) => {
        toast.ok(`Checked ${s.attempted}: ${s.ok} ok, ${s.changed} updated${s.failed > 0 ? `, ${s.failed} failed` : ''}${s.skipped > 0 ? `, ${s.skipped} no login` : ''}`)
        list.reload()
      })
      .catch((e: Error) => toast.err(e.message))
      .finally(() => setRefreshing(false))
  }

  const raiseTopup = (r: SmsBalanceRow) => {
    if (busy !== undefined) return
    setBusy(r.cmId)
    generateModuleRenewalQuote(r.cmId)
      .then((doc) => { toast.ok('Top-up proforma created'); nav(`/documents/${doc.id}`) })
      .catch((e: Error) => { toast.err(e.message); setBusy(undefined) })
  }

  const data = list.data
  const shown = useMemo(() => {
    const all = data?.rows ?? []
    if (scope === 'low') return all.filter((r) => r.low)
    if (scope === 'unknown') return all.filter((r) => r.balance === null)
    return all
  }, [data, scope])

  return (
    <div className="wf-page">
      <PageHeader
        title="SMS balances"
        desc="SMS credits across every client, lowest first — spot who is about to run dry and raise a top-up before they do."
        actions={managerial
          ? (
            <span style={{ display: 'inline-flex', gap: 8 }}>
              <Button onClick={() => setShowCreds((v) => !v)}>{showCreds ? 'Hide logins' : 'Show logins'}</Button>
              <Button onClick={downloadCreds}>Download logins (CSV)</Button>
              <Button tone="primary" disabled={refreshing} onClick={refreshAll}>{refreshing ? 'Checking…' : 'Refresh from gateway'}</Button>
            </span>
          )
          : undefined}
      />
      {data !== undefined && data.lowCount > 0 && scope !== 'low' && (
        <Notice tone="warn">
          {data.lowCount} client{data.lowCount === 1 ? '' : 's'} below {data.threshold.toLocaleString('en-IN')} SMS — needs a top-up.
        </Notice>
      )}
      <Toolbar>
        <FilterChips
          chips={[
            { key: 'low', label: 'Low', count: data?.lowCount ?? 0 },
            { key: 'all', label: 'All', count: data?.total ?? 0 },
            { key: 'unknown', label: 'Not recorded', count: data?.unknownCount ?? 0 },
          ]}
          active={scope}
          onChange={(k) => setScope(k as Scope)}
        />
        <span style={{ flex: 1 }} />
        {data !== undefined && <Badge>threshold {data.threshold.toLocaleString('en-IN')}</Badge>}
      </Toolbar>
      {list.error !== undefined ? <ErrorState message={list.error} onRetry={list.reload} />
        : data === undefined ? <Skeleton rows={6} />
        : shown.length === 0 ? (
          <EmptyState>
            {scope === 'low' ? 'No SMS client is below the low-balance threshold — all topped up.'
              : scope === 'unknown' ? 'Every SMS client has a balance recorded.'
              : 'No SMS clients yet.'}
          </EmptyState>
        ) : (
        <DataTable
          columns={[
            { key: 'client', label: 'Client' },
            { key: 'balance', label: 'Balance', numeric: true },
            ...(managerial && showCreds
              ? [{ key: 'username', label: 'Username', mono: true }, { key: 'password', label: 'Password', mono: true }]
              : []),
            { key: 'provider', label: 'Provider' },
            { key: 'checked', label: 'Checked' },
            { key: 'actions', label: '' },
          ]}
          rowTone={(i) => (shown[i]!.low ? 'err' : undefined)}
          rows={shown.map((r) => ({
            client: <Link to={`/clients/${r.clientId}?tab=modules`}>{r.clientCode} · {r.clientName}</Link>,
            balance: r.balance === null
              ? <span style={{ opacity: 0.55 }}>not recorded</span>
              : (
                <Badge tone={r.low ? 'red' : 'green'}>
                  {r.balance.toLocaleString('en-IN')}
                </Badge>
              ),
            username: r.username ?? <span style={{ opacity: 0.4 }}>—</span>,
            password: r.password !== null && r.password !== ''
              ? r.password
              : <span style={{ opacity: 0.4 }}>{r.hasCreds ? '(set)' : '—'}</span>,
            provider: r.provider ?? '—',
            checked: r.checkStatus === 'error'
              ? <span title={r.checkMessage ?? ''} style={{ color: 'var(--err)', fontSize: 12.5 }}>⚠ {ago(r.checkedAt)}</span>
              : !r.hasCreds
                ? <span style={{ opacity: 0.5, fontSize: 12.5 }}>no login</span>
                : <span style={{ opacity: 0.7, fontSize: 12.5 }}>{ago(r.checkedAt)}</span>,
            actions: (
              <span onClick={(e) => e.stopPropagation()}>
                <Button tone="primary" disabled={busy !== undefined} onClick={() => raiseTopup(r)}>
                  {busy === r.cmId ? '…' : 'Top-up quote'}
                </Button>
              </span>
            ),
          }))}
        />
      )}
    </div>
  )
}
