
import * as ActionIcons from './Icons';
import Link from 'next/link';
import { ArrowRightIcon, ChevronLeftIcon, ChevronRightIcon, InboxIcon, LockIcon, SearchIcon } from './Icons';
import { FlashBanner } from './FlashBanner';

export function PageHeader({ title, description, actions, icon }: { title: string; description?: React.ReactNode; actions?: React.ReactNode; icon?: React.ReactNode }) {
  return (
    <div className="mb-6 flex flex-wrap items-start justify-between gap-4 border-b border-rule pb-5">
      <div className="flex min-w-0 items-start gap-3.5">
        {icon && <span className="grid h-11 w-11 shrink-0 place-items-center rounded-xl bg-ledger-soft text-ledger">{icon}</span>}
        <div className="min-w-0">
          <h1 className="font-serif text-2xl font-semibold leading-tight tracking-tight">{title}</h1>
          {description && <div className="mt-1 max-w-3xl text-sm leading-relaxed text-muted">{description}</div>}
        </div>
      </div>
      {actions && <div className="flex flex-wrap items-center gap-2">{actions}</div>}
    </div>
  );
}

/** Result of a server action, passed back through ?ok= / ?err= */
export function Flash({ ok, err }: { ok?: string; err?: string }) {
  if (!ok && !err) return null;
  return <FlashBanner tone={err ? 'error' : 'success'} message={(err ?? ok)!} />;
}

export function Card({ title, children, actions, className = '', icon }: { title?: React.ReactNode; children: React.ReactNode; actions?: React.ReactNode; className?: string; icon?: React.ReactNode }) {
  return (
    <section className={`card overflow-hidden ${className}`}>
      {title && (
        <div className="flex items-center justify-between gap-3 border-b border-rule px-4 py-3">
          <h2 className="flex items-center gap-2 text-sm font-semibold text-ink">
            {icon && <span className="text-muted">{icon}</span>}
            {title}
          </h2>
          {actions}
        </div>
      )}
      {children}
    </section>
  );
}

const TONE: Record<string, string> = {
  good: 'bg-ledger-soft text-ledger',
  warn: 'bg-brass-soft text-brass',
  bad: 'bg-danger-soft text-danger',
  muted: 'bg-sunken text-muted',
  info: 'bg-sponsor-soft text-sponsor',
};
const STATUS_TONE: Record<string, keyof typeof TONE> = {
  verified: 'good',
  published: 'good',
  active: 'good',
  completed: 'good',
  accepted: 'good',
  retained: 'good',
  resolved: 'good',
  succeeded: 'good',
  paid: 'good',
  live: 'info',
  index: 'good',
  delivered: 'info',
  routed: 'info',
  viewed: 'info',
  running: 'info',
  queued: 'info',
  in_review: 'info',
  contacted: 'info',
  pending: 'warn',
  new: 'warn',
  open: 'warn',
  noindex: 'warn',
  draft: 'muted',
  unverified: 'muted',
  trialing: 'info',
  past_due: 'bad',
  expired: 'warn',
  rejected: 'bad',
  failed: 'bad',
  spam: 'bad',
  suspended: 'bad',
  revoked: 'bad',
  declined: 'muted',
  canceled: 'muted',
  merged: 'muted',
  dismissed: 'muted',
  closed: 'muted',
  archived: 'muted',
  ended: 'muted',
};

export function Pill({ value, tone }: { value: string; tone?: keyof typeof TONE }) {
  const t = tone ?? STATUS_TONE[value] ?? 'muted';
  return (
    <span className={`inline-flex items-center gap-1.5 whitespace-nowrap rounded-full px-2 py-0.5 text-[11px] font-semibold capitalize leading-4 ${TONE[t]}`}>
      <span aria-hidden className="h-1.5 w-1.5 rounded-full bg-current opacity-80" />
      {value.replace(/_/g, ' ')}
    </span>
  );
}

export function Kpi({ label, value, hint, href, icon, tone = 'default' }: { label: string; value: React.ReactNode; hint?: React.ReactNode; href?: string; icon?: React.ReactNode; tone?: 'default' | 'warn' | 'muted' }) {
  const body = (
    <>
      <div className="flex items-start justify-between gap-2">
        <p className="text-xs font-medium text-muted">{label}</p>
        {icon && <span className={`grid h-8 w-8 shrink-0 place-items-center rounded-lg ${tone === 'warn' ? 'bg-brass-soft text-brass' : tone === 'muted' ? 'bg-sunken text-muted' : 'bg-ledger-soft text-ledger'}`}>{icon}</span>}
      </div>
      <div className="num mt-1 font-serif text-[1.65rem] font-semibold leading-tight">{value}</div>
      {hint && <p className="mt-1 text-xs leading-snug text-muted">{hint}</p>}
      {href && <ArrowRightIcon className="absolute bottom-4 right-4 h-3.5 w-3.5 text-muted opacity-0 transition-all group-hover:translate-x-0.5 group-hover:text-ledger group-hover:opacity-100" />}
    </>
  );
  return href ? (
    <Link href={href} className="card card-hover group relative block p-4">
      {body}
    </Link>
  ) : (
    <div className="card relative p-4">{body}</div>
  );
}

function windowed(page: number, count: number): (number | null)[] {
  const pages = [...new Set([1, count, page - 1, page, page + 1].filter((p) => p >= 1 && p <= count))].sort((a, b) => a - b);
  const out: (number | null)[] = [];
  pages.forEach((p, i) => {
    if (i > 0 && p - pages[i - 1] > 1) out.push(null);
    out.push(p);
  });
  return out;
}

export function Pager({ page, pageCount, href, total }: { page: number; pageCount: number; href: (p: number) => string; total?: number }) {
  if (pageCount <= 1) return total != null ? <p className="num border-t border-rule px-4 py-2.5 text-xs text-muted">{total.toLocaleString('en-US')} total</p> : null;
  const cell = 'num inline-flex h-8 min-w-8 items-center justify-center rounded-md px-2 text-xs font-semibold transition-colors';
  return (
    <nav aria-label="Pagination" className="flex flex-wrap items-center justify-between gap-2 border-t border-rule bg-paper/60 px-4 py-2.5 text-sm">
      {page > 1 ? (
        <Link className="btn btn-quiet btn-sm" href={href(page - 1)} rel="prev">
          <ChevronLeftIcon className="h-4 w-4" /> Previous
        </Link>
      ) : (
        <span className="btn btn-quiet btn-sm" aria-disabled="true">
          <ChevronLeftIcon className="h-4 w-4" /> Previous
        </span>
      )}
      <ol className="flex items-center gap-1">
        {windowed(page, pageCount).map((p, i) =>
          p == null ? (
            <li key={`g${i}`} aria-hidden className="px-1 text-muted">
              …
            </li>
          ) : (
            <li key={p}>
              {p === page ? (
                <span aria-current="page" className={`${cell} bg-ledger text-ledger-ink`}>
                  {p}
                </span>
              ) : (
                <Link href={href(p)} className={`${cell} text-ink-2 hover:bg-sunken hover:text-ink`}>
                  {p}
                </Link>
              )}
            </li>
          ),
        )}
        {total != null && <li className="num ml-2 hidden text-xs text-muted sm:block">{total.toLocaleString('en-US')} total</li>}
      </ol>
      {page < pageCount ? (
        <Link className="btn btn-quiet btn-sm" href={href(page + 1)} rel="next">
          Next <ChevronRightIcon className="h-4 w-4" />
        </Link>
      ) : (
        <span className="btn btn-quiet btn-sm" aria-disabled="true">
          Next <ChevronRightIcon className="h-4 w-4" />
        </span>
      )}
    </nav>
  );
}

export function Empty({ children, icon }: { children: React.ReactNode; icon?: React.ReactNode }) {
  return (
    <div className="flex flex-col items-center px-4 py-12 text-center">
      <span className="grid h-12 w-12 place-items-center rounded-xl bg-sunken text-muted">{icon ?? <InboxIcon className="h-6 w-6" />}</span>
      <p className="mt-3 max-w-sm text-sm text-muted">{children}</p>
    </div>
  );
}

/** Segmented status filter (e.g. pending / verified / rejected) */
export function Tabs({ items, current }: { items: { value: string; label: string; href: string; count?: number }[]; current: string }) {
  return (
    <nav aria-label="Filter" className="inline-flex flex-wrap gap-1 rounded-lg border border-rule bg-sunken p-1">
      {items.map((t) => (
        <Link key={t.value} href={t.href} aria-current={t.value === current ? 'page' : undefined} className="tab">
          {t.label}
          {t.count != null && <span className="num rounded bg-sunken px-1 text-[10px] text-muted">{t.count}</span>}
        </Link>
      ))}
    </nav>
  );
}

/** Text input with a leading search icon, for filter toolbars */
export function SearchField({ name, defaultValue, placeholder, className = 'max-w-xs' }: { name: string; defaultValue?: string; placeholder: string; className?: string }) {
  return (
    <label className={`relative block w-full ${className}`}>
      <span className="sr-only">{placeholder}</span>
      <SearchIcon className="pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted" />
      <input name={name} type="search" defaultValue={defaultValue} placeholder={placeholder} className="field pl-8" />
    </label>
  );
}

export function Toolbar({ children }: { children: React.ReactNode }) {
  return <form className="mb-4 flex flex-wrap items-center gap-2">{children}</form>;
}

/** Shown instead of a page the signed-in role may not open */
export function Forbidden({ what }: { what: string }) {
  return (
    <div className="card mx-auto mt-10 flex max-w-lg flex-col items-center p-10 text-center">
      <span className="grid h-14 w-14 place-items-center rounded-2xl bg-brass-soft text-brass">
        <LockIcon className="h-7 w-7" />
      </span>
      <h1 className="mt-4 font-serif text-xl font-semibold">You don’t have access to {what}</h1>
      <p className="mt-2 text-sm text-muted">This area is limited to administrators. Ask an admin if you need it.</p>
      <Link href="/" className="btn btn-quiet btn-sm mt-6">
        <ActionIcons.ArrowLeftIcon />Back to the dashboard
      </Link>
    </div>
  );
}

export type SP = Promise<Record<string, string | undefined>>;
