import { useDeferredValue, useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import type { ColumnDef } from '@tanstack/react-table';
import type { PermissionGrant } from '@pig/core';
import { Building2, Mail, Pencil, Plus, RefreshCw, Search, UserPlus } from 'lucide-react';
import { AccountSheet, ContactSheet, type AccountRecord, type ContactRecord, type ContactRow } from '@/components/RecordSheets';
import { DataTable, DataTableColumnHeader } from '@/components/DataTable';
import { Badge, Button, Card, ConfidenceBadge, EmptyState, Input, Skeleton } from '@/components/ui';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { get, relativeTime } from '@/lib/api';
import { can } from '@/lib/permissions';
import { usePageTitle } from '@/lib/title';

interface Me { permissions: PermissionGrant[] }
type View = 'accounts' | 'contacts';

export function Accounts() {
  usePageTitle('Accounts');
  const [side, setSide] = useState<'all' | 'supply' | 'demand'>('all');
  const [view, setView] = useState<View>('accounts');
  const [mobileSearch, setMobileSearch] = useState('');
  const deferredSearch = useDeferredValue(mobileSearch.trim().toLocaleLowerCase());
  const [accountSheet, setAccountSheet] = useState<{ open: boolean; record?: AccountRecord }>({ open: false });
  const [contactSheet, setContactSheet] = useState<{ open: boolean; record?: ContactRecord; accountId?: string }>({ open: false });
  const { data: me } = useQuery({ queryKey: ['me'], queryFn: () => get<Me>('/api/me') });
  const accountsQuery = useQuery({ queryKey: ['accounts', side], queryFn: () => get<AccountRecord[]>(`/api/accounts${side === 'all' ? '' : `?side=${side}`}`) });
  const contactsQuery = useQuery({ queryKey: ['contacts', 'table'], queryFn: () => get<ContactRow[]>('/api/contacts') });
  const canDemand = can(me, 'deal:write', 'demand');
  const canSupply = can(me, 'deal:write', 'supply');
  const canAny = canDemand || canSupply;
  const canAccount = (account: AccountRecord) => account.side === 'both' ? canAny : account.side === 'demand' ? canDemand : canSupply;
  const canContact = (row: ContactRow) => row.accountSide === 'both' ? canAny : row.accountSide === 'demand' ? canDemand : row.accountSide === 'supply' ? canSupply : false;
  const visibleAccounts = useMemo(() => !deferredSearch ? accountsQuery.data ?? [] : (accountsQuery.data ?? []).filter((account) => [account.name, account.domain, account.country, account.supplierType, account.customerSegment].some((value) => value?.toLocaleLowerCase().includes(deferredSearch))), [accountsQuery.data, deferredSearch]);
  const visibleContacts = useMemo(() => !deferredSearch ? contactsQuery.data ?? [] : (contactsQuery.data ?? []).filter((row) => [row.contact.fullName, row.contact.email, row.contact.title, row.accountName].some((value) => value?.toLocaleLowerCase().includes(deferredSearch))), [contactsQuery.data, deferredSearch]);

  const accountColumns: ColumnDef<AccountRecord>[] = [
    { id: 'account', accessorFn: (account) => `${account.name} ${account.domain ?? ''}`, header: ({ column }) => <DataTableColumnHeader column={column} title="Account" />, cell: ({ row }) => <div className="min-w-0 max-w-xs"><p className="truncate font-medium">{row.original.name}</p>{row.original.domain ? <p className="truncate text-xs text-muted">{row.original.domain}</p> : null}</div> },
    { accessorKey: 'side', header: ({ column }) => <DataTableColumnHeader column={column} title="Side" />, cell: ({ row }) => <SideBadge side={row.original.side} /> },
    { id: 'type', accessorFn: (account) => account.supplierType ?? account.customerSegment ?? '', header: ({ column }) => <DataTableColumnHeader column={column} title="Type" />, cell: ({ row }) => { const type = accountType(row.original); return type ? <span className="capitalize">{type.replace(/_/g, ' ')}</span> : '—'; } },
    { accessorKey: 'country', header: ({ column }) => <DataTableColumnHeader column={column} title="Country" />, cell: ({ row }) => row.original.country ?? '—' },
    { accessorKey: 'confidence', header: ({ column }) => <DataTableColumnHeader column={column} title="Confidence" />, cell: ({ row }) => <Confidence confidence={row.original.confidence} /> },
    { accessorKey: 'lastActivityAt', header: ({ column }) => <DataTableColumnHeader column={column} title="Last activity" />, cell: ({ row }) => row.original.lastActivityAt ? relativeTime(row.original.lastActivityAt) : '—' },
    { id: 'actions', enableHiding: false, enableSorting: false, header: 'Actions', cell: ({ row }) => <div className="flex justify-end gap-1"><Button size="icon" variant="ghost" title="Add contact" disabled={!canAccount(row.original)} onClick={() => setContactSheet({ open: true, accountId: row.original.id })}><UserPlus aria-hidden /><span className="sr-only">Add contact to {row.original.name}</span></Button><Button size="icon" variant="ghost" title="Edit account" disabled={!canAccount(row.original)} onClick={() => setAccountSheet({ open: true, record: row.original })}><Pencil aria-hidden /><span className="sr-only">Edit {row.original.name}</span></Button></div> },
  ];
  const contactColumns: ColumnDef<ContactRow>[] = [
    { id: 'contact', accessorFn: (row) => `${row.contact.fullName} ${row.contact.email ?? ''}`, header: ({ column }) => <DataTableColumnHeader column={column} title="Contact" />, cell: ({ row }) => <div className="min-w-0 max-w-xs"><p className="truncate font-medium">{row.original.contact.fullName}</p>{row.original.contact.email ? <p className="truncate text-xs text-muted">{row.original.contact.email}</p> : <p className="text-xs text-muted">No email recorded</p>}</div> },
    { accessorKey: 'accountName', header: ({ column }) => <DataTableColumnHeader column={column} title="Account" />, cell: ({ row }) => row.original.accountName ?? 'Unassigned' },
    { id: 'title', accessorFn: (row) => row.contact.title ?? '', header: ({ column }) => <DataTableColumnHeader column={column} title="Title" />, cell: ({ row }) => row.original.contact.title ?? '—' },
    { id: 'affiliation', accessorFn: (row) => row.contact.affiliation, header: ({ column }) => <DataTableColumnHeader column={column} title="Affiliation" />, cell: ({ row }) => <span className="capitalize">{row.original.contact.affiliation.replace(/_/g, ' ')}</span> },
    { id: 'confidence', accessorFn: (row) => row.contact.confidence, header: ({ column }) => <DataTableColumnHeader column={column} title="Confidence" />, cell: ({ row }) => <Confidence confidence={row.original.contact.confidence} /> },
    { id: 'lastActivityAt', accessorFn: (row) => row.contact.lastActivityAt ?? '', header: ({ column }) => <DataTableColumnHeader column={column} title="Last activity" />, cell: ({ row }) => row.original.contact.lastActivityAt ? relativeTime(row.original.contact.lastActivityAt) : '—' },
    { id: 'actions', enableHiding: false, enableSorting: false, header: 'Actions', cell: ({ row }) => <div className="flex justify-end"><Button size="icon" variant="ghost" title="Edit contact" disabled={!canContact(row.original)} onClick={() => setContactSheet({ open: true, record: row.original.contact })}><Pencil aria-hidden /><span className="sr-only">Edit {row.original.contact.fullName}</span></Button></div> },
  ];
  const activeQuery = view === 'accounts' ? accountsQuery : contactsQuery;
  const count = view === 'accounts' ? accountsQuery.data?.length ?? 0 : contactsQuery.data?.length ?? 0;

  return <div className="flex flex-col gap-5">
    <header className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between"><div><h1 className="text-xl font-semibold tracking-tight sm:text-2xl">Accounts</h1><p className="mt-1 max-w-2xl text-sm text-muted">Providers we buy from, customers we sell to, and the people who make each relationship real.</p></div><div className="grid grid-cols-2 gap-2 sm:flex"><Button className="min-h-11" variant="outline" disabled={!canAny} onClick={() => setContactSheet({ open: true })}><UserPlus aria-hidden />New contact</Button><Button className="min-h-11" variant="primary" disabled={!canAny} onClick={() => setAccountSheet({ open: true })}><Plus aria-hidden />New account</Button></div></header>
    <section className="rounded-xl border border-border bg-surface-2/60 p-3"><div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"><Tabs value={view} onValueChange={(value) => { setView(value as View); setMobileSearch(''); }}><TabsList className="grid min-h-[52px] w-full grid-cols-2 border border-border bg-surface p-1 sm:w-64"><TabsTrigger className="min-h-11 text-muted data-[state=active]:bg-surface-2 data-[state=active]:text-fg" value="accounts">Accounts</TabsTrigger><TabsTrigger className="min-h-11 text-muted data-[state=active]:bg-surface-2 data-[state=active]:text-fg" value="contacts">Contacts</TabsTrigger></TabsList></Tabs><p className="text-sm text-muted"><strong className="nums text-fg">{count}</strong> {view}{view === 'accounts' && side !== 'all' ? ` · ${side}` : ''}</p></div>{view === 'accounts' ? <div className="mt-3 grid grid-cols-3 gap-1 rounded-lg bg-surface p-1 sm:ml-auto sm:w-fit">{(['all', 'supply', 'demand'] as const).map((value) => <button key={value} onClick={() => setSide(value)} aria-label={`Show ${value} accounts`} aria-pressed={side === value} className={['min-h-11 rounded-md px-4 text-sm font-medium capitalize transition-colors', side === value ? 'bg-surface-2 text-fg shadow-sm' : 'text-muted hover:text-fg'].join(' ')}>{value}</button>)}</div> : null}</section>
    <label className="relative md:hidden"><span className="sr-only">Search {view}</span><Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted" aria-hidden /><Input className="h-11 pl-9" value={mobileSearch} onChange={(event) => setMobileSearch(event.target.value)} placeholder={view === 'accounts' ? 'Search account, country or type' : 'Search contact, account or title'} /></label>
    {activeQuery.isLoading ? <Skeleton className="h-64" /> : null}
    {activeQuery.isError ? <Card><EmptyState title={`${view === 'accounts' ? 'Accounts' : 'Contacts'} unavailable`} description={activeQuery.error.message} action={<Button variant="outline" onClick={() => void activeQuery.refetch()}><RefreshCw aria-hidden />Try again</Button>} /></Card> : null}
    {!activeQuery.isLoading && !activeQuery.isError && view === 'accounts' ? <><div className="hidden md:block"><DataTable columns={accountColumns} data={accountsQuery.data ?? []} filterColumn="account" filterPlaceholder="Search account names or domains" emptyMessage="No accounts found." /></div><div className="grid gap-3 md:hidden">{visibleAccounts.map((account) => <AccountCard key={account.id} account={account} writable={canAccount(account)} onAddContact={() => setContactSheet({ open: true, accountId: account.id })} onEdit={() => setAccountSheet({ open: true, record: account })} />)}{visibleAccounts.length === 0 ? <Card><EmptyState icon={<Building2 />} title={accountsQuery.data?.length ? 'No accounts match' : `No ${side === 'all' ? '' : `${side} `}accounts`} description={accountsQuery.data?.length ? 'Try a broader search.' : 'No relationship records are available in this view.'} /></Card> : null}</div></> : null}
    {!activeQuery.isLoading && !activeQuery.isError && view === 'contacts' ? <><div className="hidden md:block"><DataTable columns={contactColumns} data={contactsQuery.data ?? []} filterColumn="contact" filterPlaceholder="Search contact names or email" emptyMessage="No contacts found." /></div><div className="grid gap-3 md:hidden">{visibleContacts.map((row) => <ContactCard key={row.contact.id} row={row} writable={canContact(row)} onEdit={() => setContactSheet({ open: true, record: row.contact })} />)}{visibleContacts.length === 0 ? <Card><EmptyState icon={<Mail />} title={contactsQuery.data?.length ? 'No contacts match' : 'No contacts recorded'} description={contactsQuery.data?.length ? 'Try a broader search.' : 'Add a sourced contact to an account when the relationship is known.'} /></Card> : null}</div></> : null}
    <AccountSheet open={accountSheet.open} onOpenChange={(open) => setAccountSheet((state) => ({ ...state, open }))} record={accountSheet.record} identity={me} /><ContactSheet open={contactSheet.open} onOpenChange={(open) => setContactSheet((state) => ({ ...state, open }))} record={contactSheet.record} defaultAccountId={contactSheet.accountId} identity={me} />
  </div>;
}

function AccountCard({ account, writable, onAddContact, onEdit }: { account: AccountRecord; writable: boolean; onAddContact(): void; onEdit(): void }) { const type = accountType(account); return <article className="card min-w-0 p-4"><div className="flex items-start justify-between gap-3"><div className="min-w-0"><p className="truncate font-semibold">{account.name}</p><p className="mt-0.5 truncate text-sm text-muted">{account.domain ?? 'No domain recorded'}</p></div><SideBadge side={account.side} /></div><div className="mt-3 grid grid-cols-2 gap-2 text-sm"><RecordValue label="Relationship" value={type ? type.replace(/_/g, ' ') : 'Not classified'} /><RecordValue label="Geography" value={account.country ?? 'Not recorded'} /><RecordValue label="Confidence" value={<Confidence confidence={account.confidence} />} /><RecordValue label="Last activity" value={account.lastActivityAt ? relativeTime(account.lastActivityAt) : 'No activity'} /></div><div className="mt-3 grid grid-cols-2 gap-2 border-t border-border pt-3"><Button className="min-h-11" variant="outline" disabled={!writable} onClick={onAddContact}><UserPlus aria-hidden />Add contact</Button><Button className="min-h-11" variant="ghost" disabled={!writable} onClick={onEdit}><Pencil aria-hidden />Edit account</Button></div></article>; }
function ContactCard({ row, writable, onEdit }: { row: ContactRow; writable: boolean; onEdit(): void }) { return <article className="card min-w-0 p-4"><div className="flex items-start justify-between gap-3"><div className="min-w-0"><p className="truncate font-semibold">{row.contact.fullName}</p><p className="mt-0.5 truncate text-sm text-muted">{row.contact.title ?? 'No title recorded'}</p></div><Badge tone="neutral">{row.contact.affiliation.replace(/_/g, ' ')}</Badge></div><div className="mt-3 grid grid-cols-2 gap-2 text-sm"><RecordValue label="Account" value={row.accountName ?? 'Unassigned'} /><RecordValue label="Email" value={row.contact.email ?? 'Not recorded'} /><RecordValue label="Confidence" value={<Confidence confidence={row.contact.confidence} />} /><RecordValue label="Last activity" value={row.contact.lastActivityAt ? relativeTime(row.contact.lastActivityAt) : 'No activity'} /></div><Button className="mt-3 min-h-11 w-full border-t border-border" variant="ghost" disabled={!writable} onClick={onEdit}><Pencil aria-hidden />Edit contact</Button></article>; }
function RecordValue({ label, value }: { label: string; value: React.ReactNode }) { return <div className="min-w-0 rounded-lg bg-surface-2 p-2.5"><p className="text-[11px] uppercase tracking-wide text-muted">{label}</p><div className="mt-1 truncate capitalize text-xs font-medium">{value}</div></div>; }
function SideBadge({ side }: { side: AccountRecord['side'] }) { return <Badge tone={side === 'supply' ? 'info' : side === 'both' ? 'accent' : 'neutral'}>{side === 'supply' ? 'Buy-side' : side === 'demand' ? 'Sell-side' : 'Both sides'}</Badge>; }
function Confidence({ confidence }: { confidence: string }) { return confidence === 'confirmed' ? <span className="text-muted">Confirmed</span> : <ConfidenceBadge confidence={confidence} />; }
function accountType(account: AccountRecord) { return account.supplierType ?? account.customerSegment; }
