import type { Metadata } from 'next';
import Link from 'next/link';
import { addDaysToDate, businessDate, forVenue, getDb } from '@pintrush/db';
import { formatBusinessDate, formatNumber, formatPercent } from '@/components/host/format';
import { Notice, PageHeader, Panel, StatCard, TableWrap, td, th } from '@/components/host/ui';
import { cn } from '@/lib/cn';
import { requireHost } from '@/lib/auth/session';
import { dailyJoins } from '../../_lib/data';

export const metadata: Metadata = { title: 'Metrics' };

const RANGES = [7, 30, 90] as const;
type Range = (typeof RANGES)[number];
const DAY_MS = 86_400_000;
/** Spec §11 pilot hypothesis. */
const RETURN_TARGET = 0.3;

function parseRange(value: string | string[] | undefined): Range {
  const n = Number(Array.isArray(value) ? value[0] : value);
  return (RANGES as readonly number[]).includes(n) ? (n as Range) : 30;
}

export default async function MetricsPage({ searchParams }: { searchParams: Promise<Record<string, string | string[] | undefined>> }) {
  const { venue } = await requireHost('/host/metrics');
  const range = parseRange((await searchParams).range);
  const now = Date.now();
  const from = new Date(now - range * DAY_MS);
  const to = new Date(now);
  const [metrics, daily] = await Promise.all([forVenue(getDb(), venue.id).metrics({ from, to }), dailyJoins(venue.id, venue.timezone, from, to)]);

  // One bar per business date in the range, including nights nobody played.
  const byDate = new Map(daily.map((d) => [d.date, d]));
  const lastDate = businessDate(venue.timezone, now);
  const dates = Array.from({ length: range }, (_, i) => addDaysToDate(lastDate, i - range + 1));
  const series = dates.map((date) => byDate.get(date) ?? { date, joins: 0, guests: 0 });
  const realPeak = Math.max(0, ...series.map((d) => d.joins));
  const peak = Math.max(1, realPeak);
  const repeatRate = metrics.uniqueGuests > 0 ? metrics.repeatPlayers / metrics.uniqueGuests : 0;
  const nightsWithPlay = series.filter((d) => d.joins > 0).length;
  const totalEvents = metrics.eventsByKind.ALWAYS_ON + metrics.eventsByKind.CHAMPIONSHIP;

  return (
    <div className="flex flex-col gap-8">
      <PageHeader
        title="Metrics"
        description="Guests are counted by an anonymous device id — no names, emails or phone numbers are collected."
        actions={
          <nav aria-label="Date range" className="inline-flex rounded-xl border border-line bg-surface p-1">
            {RANGES.map((r) => (
              <Link
                key={r}
                href={`/host/metrics?range=${r}`}
                aria-current={r === range ? 'page' : undefined}
                className={cn(
                  'inline-flex min-h-11 items-center rounded-lg px-4 text-sm font-semibold',
                  r === range ? 'bg-violet/25 text-fg shadow-[inset_0_0_0_1px_rgb(124_92_255/0.55)]' : 'text-muted hover:text-fg',
                )}
              >
                {r} days
              </Link>
            ))}
          </nav>
        }
      />

      <dl className="grid grid-cols-2 gap-3 lg:grid-cols-4">
        <StatCard label="Unique guests" value={formatNumber(metrics.uniqueGuests)} hint={`last ${range} days`} tone="violet" />
        <StatCard label="Joins" value={formatNumber(metrics.joins)} hint={metrics.uniqueGuests ? `${(metrics.joins / metrics.uniqueGuests).toFixed(1)} per guest` : undefined} tone="cyan" />
        <StatCard label="Rounds completed" value={formatNumber(metrics.roundsCompleted)} hint={`${nightsWithPlay} night${nightsWithPlay === 1 ? '' : 's'} with play`} tone="lime" />
        <StatCard label="Repeat players" value={formatNumber(metrics.repeatPlayers)} hint="played on 2+ different nights" tone="amber" />
      </dl>

      <div className="grid gap-8 lg:grid-cols-[1.6fr_1fr]">
        <Panel title="Joins per night" description="Business nights run until 5 am, so a 1 am join counts for the night before.">
          <div className="flex h-48 items-end gap-[2px]" aria-hidden="true">
            {series.map((d) => (
              <div key={d.date} className="group relative flex h-full flex-1 items-end" title={`${formatBusinessDate(d.date)}: ${d.joins} joins, ${d.guests} guests`}>
                <div
                  className={cn('w-full rounded-t-sm', d.joins > 0 ? 'bg-[linear-gradient(180deg,var(--color-cyan),var(--color-violet))]' : 'bg-line/60')}
                  style={{ height: `${d.joins > 0 ? Math.max(4, (d.joins / peak) * 100) : 2}%` }}
                />
              </div>
            ))}
          </div>
          <div className="mt-2 flex justify-between text-xs text-subtle" aria-hidden="true">
            <span>{formatBusinessDate(series[0]!.date)}</span>
            <span>peak {formatNumber(realPeak)}</span>
            <span>{formatBusinessDate(series[series.length - 1]!.date)}</span>
          </div>
          <details className="mt-4 text-sm">
            <summary className="inline-flex min-h-11 items-center font-semibold text-violet-soft hover:text-fg">Show as a table</summary>
            <div className="mt-2 px-5 sm:px-6">
              <TableWrap label="Joins per night">
                <thead>
                  <tr>
                    <th scope="col" className={th}>
                      Night
                    </th>
                    <th scope="col" className={`${th} text-right`}>
                      Joins
                    </th>
                    <th scope="col" className={`${th} text-right`}>
                      Guests
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {[...series].reverse().map((d) => (
                    <tr key={d.date}>
                      <td className={td}>{formatBusinessDate(d.date)}</td>
                      <td className={`${td} num text-right`}>{d.joins}</td>
                      <td className={`${td} num text-right`}>{d.guests}</td>
                    </tr>
                  ))}
                </tbody>
              </TableWrap>
            </div>
          </details>
        </Panel>

        <div className="flex flex-col gap-8">
          <Panel title="Coming back">
            <p className="num font-display text-4xl font-bold">{metrics.uniqueGuests ? formatPercent(repeatRate) : '—'}</p>
            <p className="mt-1 text-sm text-muted">of guests played on more than one night in the last {range} days.</p>
            <div
              className="relative mt-5 h-3 rounded-full bg-line/70"
              role="meter"
              aria-label="Share of guests who came back"
              aria-valuemin={0}
              aria-valuemax={100}
              aria-valuenow={Math.round(repeatRate * 100)}
              aria-valuetext={`${formatPercent(repeatRate)}, target 30%`}
            >
              <div
                className={cn('h-full rounded-full', repeatRate >= RETURN_TARGET ? 'bg-lime' : 'bg-amber')}
                style={{ width: `${Math.min(100, repeatRate * 100)}%` }}
              />
              <div className="absolute inset-y-[-4px] w-0.5 bg-fg" style={{ left: `${RETURN_TARGET * 100}%` }} aria-hidden="true" />
            </div>
            <p className="mt-2 text-xs text-subtle">
              Pilot target: <strong className="text-fg">≥ 30%</strong> of identifiable players returning within 30 days (a hypothesis, not a benchmark).
            </p>
          </Panel>
          <Panel title="Events started">
            <ul className="flex flex-col gap-3">
              {(
                [
                  ['Always-on nights', metrics.eventsByKind.ALWAYS_ON, 'bg-cyan'],
                  ['Championships', metrics.eventsByKind.CHAMPIONSHIP, 'bg-violet'],
                ] as const
              ).map(([label, count, color]) => (
                <li key={label}>
                  <div className="flex justify-between text-sm">
                    <span className="text-muted">{label}</span>
                    <span className="num font-semibold">{formatNumber(count)}</span>
                  </div>
                  <div className="mt-1.5 h-2 rounded-full bg-line/70" aria-hidden="true">
                    <div className={cn('h-full rounded-full', color)} style={{ width: `${totalEvents ? (count / totalEvents) * 100 : 0}%` }} />
                  </div>
                </li>
              ))}
            </ul>
          </Panel>
        </div>
      </div>
      {metrics.joins === 0 && (
        <Notice tone="info" title="No play recorded in this range yet">
          Numbers fill in as soon as guests join from the QR code on your TV.
        </Notice>
      )}
    </div>
  );
}
