'use client';

import Link from 'next/link';
import { useEffect, useMemo, useState } from 'react';
import { ArrowLeft, BarChart3, Coins, Database, Filter, Gauge, MessageSquareText, Sigma } from 'lucide-react';
import { Badge, Button } from '@/components/ui/Primitives';
import { HermesShell, MetricCard, SectionCard } from '@/components/hermes-shell';
import { HermesInstanceBadge } from '@/components/hermes-instance-switcher';
import { useHermesInstance } from '@/lib/hermes-instance-context';
import { api, type HermesTokenSession, type HermesTokenUsageSnapshot } from '@/lib/api';

type InstanceId = 'vijay' | 'bheem';
const INSTANCE_IDS: InstanceId[] = ['vijay', 'bheem'];

const emptySummary = {
  sessionCount: 0,
  messageCount: 0,
  toolCallCount: 0,
  inputTokens: 0,
  outputTokens: 0,
  cacheReadTokens: 0,
  cacheWriteTokens: 0,
  reasoningTokens: 0,
  totalTokens: 0,
  estimatedCostUsd: 0,
  actualCostUsd: 0,
  firstStartedAt: null as string | null,
  lastActivityAt: null as string | null,
};

function formatInt(value: number) {
  return new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value);
}

function formatCompact(value: number) {
  return new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(value);
}

function formatUsd(value: number) {
  return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 4 }).format(value);
}

function formatDate(value: string | null) {
  if (!value) return '—';
  return new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }).format(new Date(value));
}

function tokenTotal(session: HermesTokenSession) {
  return session.totalTokens;
}

export default function HermesTokenAnalyticsPage() {
  const { selectedInstance } = useHermesInstance();
  const [snapshots, setSnapshots] = useState<Partial<Record<InstanceId, HermesTokenUsageSnapshot>>>({});
  const [error, setError] = useState<string | null>(null);
  const [query, setQuery] = useState('');
  const [minimumTokens, setMinimumTokens] = useState(0);

  useEffect(() => {
    let active = true;
    const load = async () => {
      try {
        const ids = selectedInstance === 'all' ? INSTANCE_IDS : [selectedInstance as InstanceId];
        const pairs = await Promise.all(ids.map(async (id) => [id, await api.getHermesTokenUsage(id)] as const));
        if (!active) return;
        setSnapshots((current) => ({ ...current, ...Object.fromEntries(pairs) }));
        setError(null);
      } catch (err) {
        if (!active) return;
        setError(err instanceof Error ? err.message : String(err));
      }
    };
    void load();
    const timer = window.setInterval(load, 60_000);
    return () => {
      active = false;
      window.clearInterval(timer);
    };
  }, [selectedInstance]);

  const visibleSnapshots = useMemo(() => {
    const ids = selectedInstance === 'all' ? INSTANCE_IDS : [selectedInstance as InstanceId];
    return ids.map((id) => snapshots[id]).filter(Boolean) as HermesTokenUsageSnapshot[];
  }, [selectedInstance, snapshots]);

  const combinedSummary = useMemo(() => visibleSnapshots.reduce((acc, snap) => ({
    ...acc,
    sessionCount: acc.sessionCount + snap.summary.sessionCount,
    messageCount: acc.messageCount + snap.summary.messageCount,
    toolCallCount: acc.toolCallCount + snap.summary.toolCallCount,
    inputTokens: acc.inputTokens + snap.summary.inputTokens,
    outputTokens: acc.outputTokens + snap.summary.outputTokens,
    cacheReadTokens: acc.cacheReadTokens + snap.summary.cacheReadTokens,
    cacheWriteTokens: acc.cacheWriteTokens + snap.summary.cacheWriteTokens,
    reasoningTokens: acc.reasoningTokens + snap.summary.reasoningTokens,
    totalTokens: acc.totalTokens + snap.summary.totalTokens,
    estimatedCostUsd: acc.estimatedCostUsd + snap.summary.estimatedCostUsd,
    actualCostUsd: acc.actualCostUsd + snap.summary.actualCostUsd,
    firstStartedAt: [acc.firstStartedAt, snap.summary.firstStartedAt].filter(Boolean).sort()[0] ?? null,
    lastActivityAt: [acc.lastActivityAt, snap.summary.lastActivityAt].filter(Boolean).sort().at(-1) ?? null,
  }), emptySummary), [visibleSnapshots]);

  const byModel = useMemo(() => {
    const buckets = new Map<string, { model: string; provider: string; instanceIds: Set<InstanceId>; sessionCount: number; totalTokens: number; estimatedCostUsd: number }>();
    for (const snap of visibleSnapshots) {
      for (const row of snap.byModel) {
        const key = `${row.provider}\u0000${row.model}`;
        const item = buckets.get(key) ?? { model: row.model, provider: row.provider, instanceIds: new Set<InstanceId>(), sessionCount: 0, totalTokens: 0, estimatedCostUsd: 0 };
        item.instanceIds.add(snap.instanceId);
        item.sessionCount += row.sessionCount;
        item.totalTokens += row.totalTokens;
        item.estimatedCostUsd += row.estimatedCostUsd;
        buckets.set(key, item);
      }
    }
    return Array.from(buckets.values()).sort((a, b) => b.totalTokens - a.totalTokens).slice(0, 12);
  }, [visibleSnapshots]);

  const byDay = useMemo(() => {
    const buckets = new Map<string, number>();
    for (const snap of visibleSnapshots) {
      for (const row of snap.byDay) buckets.set(row.day, (buckets.get(row.day) ?? 0) + row.totalTokens);
    }
    return Array.from(buckets, ([day, totalTokens]) => ({ day, totalTokens })).sort((a, b) => a.day.localeCompare(b.day)).slice(-30);
  }, [visibleSnapshots]);

  const recentSessions = useMemo(() => {
    const q = query.trim().toLowerCase();
    return visibleSnapshots
      .flatMap((snap) => snap.recentSessions.map((session) => ({ ...session, instanceId: snap.instanceId })))
      .filter((session) => tokenTotal(session) >= minimumTokens)
      .filter((session) => !q || [session.title, session.source, session.model, session.provider].some((value) => value?.toLowerCase().includes(q)))
      .sort((a, b) => new Date(b.endedAt ?? b.startedAt ?? 0).getTime() - new Date(a.endedAt ?? a.startedAt ?? 0).getTime())
      .slice(0, 50);
  }, [minimumTokens, query, visibleSnapshots]);

  const maxDayTokens = Math.max(...byDay.map((row) => row.totalTokens), 1);
  const maxModelTokens = Math.max(...byModel.map((row) => row.totalTokens), 1);
  const cachePct = combinedSummary.totalTokens > 0 ? Math.round((combinedSummary.cacheReadTokens / combinedSummary.totalTokens) * 100) : 0;

  return (
    <HermesShell
      title="Hermes Token Analytics"
      description="Historical token usage, model/provider mix, cost fields, and session-level filters for Vijay and Bheem. Message content is not exposed."
      actions={<Button asChild><Link href="/hermes"><ArrowLeft className="mr-2 h-4 w-4" />Back to mission control</Link></Button>}
    >
      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <MetricCard label="Total tokens" value={formatCompact(combinedSummary.totalTokens)} tone="info" icon={<Sigma className="h-5 w-5" />} helpText={`${formatInt(combinedSummary.totalTokens)} lifetime tokens in selected scope`} />
        <MetricCard label="Sessions" value={formatInt(combinedSummary.sessionCount)} tone="success" icon={<MessageSquareText className="h-5 w-5" />} helpText={`${formatInt(combinedSummary.messageCount)} messages · ${formatInt(combinedSummary.toolCallCount)} tool calls`} />
        <MetricCard label="Cache read share" value={`${cachePct}%`} tone="warning" icon={<Gauge className="h-5 w-5" />} helpText={`${formatCompact(combinedSummary.cacheReadTokens)} cached tokens`} />
        <MetricCard label="Estimated cost" value={formatUsd(combinedSummary.estimatedCostUsd)} tone="default" icon={<Coins className="h-5 w-5" />} helpText={`Actual cost field: ${formatUsd(combinedSummary.actualCostUsd)}`} />
      </section>

      <SectionCard title="Per-instance token roll-up" subtitle="Vijay and Bheem usage side-by-side from their local Hermes state databases." actions={<Badge variant={error ? 'error' : 'success'}>{error ? 'Load issue' : 'Live state.db'}</Badge>}>
        {error ? <p className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4 text-sm text-[var(--bl-warning)]">Could not load token analytics: {error}</p> : null}
        <div className="grid gap-4 md:grid-cols-2">
          {visibleSnapshots.map((snap) => (
            <div key={snap.instanceId} className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4">
              <div className="flex items-start justify-between gap-3">
                <div>
                  <p className="text-base font-semibold text-[var(--bl-text-primary)]">{snap.instanceId === 'vijay' ? 'Vijay' : 'Bheem'}</p>
                  <p className="text-xs text-[var(--bl-text-secondary)]">{snap.source ?? 'state.db unavailable'}</p>
                </div>
                <div className="flex items-center gap-2"><HermesInstanceBadge instanceId={snap.instanceId} /><Badge variant={snap.status === 'up' ? 'success' : 'warning'}>{snap.status}</Badge></div>
              </div>
              <dl className="mt-4 grid grid-cols-2 gap-3 text-sm md:grid-cols-4">
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Tokens</dt><dd className="text-lg font-semibold text-[var(--bl-text-primary)]">{formatCompact(snap.summary.totalTokens)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Input</dt><dd className="text-lg font-semibold text-[var(--bl-info)]">{formatCompact(snap.summary.inputTokens)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Output</dt><dd className="text-lg font-semibold text-[var(--bl-success)]">{formatCompact(snap.summary.outputTokens)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Reasoning</dt><dd className="text-lg font-semibold text-[var(--bl-warning)]">{formatCompact(snap.summary.reasoningTokens)}</dd></div>
              </dl>
              <p className="mt-3 text-xs text-[var(--bl-text-secondary)]">Window: {formatDate(snap.summary.firstStartedAt)} → {formatDate(snap.summary.lastActivityAt)}</p>
            </div>
          ))}
        </div>
      </SectionCard>

      <div className="grid gap-6 xl:grid-cols-[1fr_1fr]">
        <SectionCard title="30-day token trend" subtitle="Daily buckets across the selected instance scope.">
          <div className="flex h-64 items-end gap-2 overflow-x-auto rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4">
            {byDay.map((row) => (
              <div key={row.day} className="flex min-w-8 flex-1 flex-col items-center gap-2">
                <div className="w-full rounded-t-md bg-[var(--bl-accent)]" style={{ height: `${Math.max(4, (row.totalTokens / maxDayTokens) * 100)}%` }} title={`${row.day}: ${formatInt(row.totalTokens)} tokens`} />
                <span className="text-[10px] text-[var(--bl-text-tertiary)]">{row.day.slice(5)}</span>
              </div>
            ))}
          </div>
        </SectionCard>

        <SectionCard title="Model/provider mix" subtitle="Top token-consuming model/provider buckets.">
          <div className="space-y-3">
            {byModel.map((row) => (
              <div key={`${row.provider}-${row.model}`} className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4">
                <div className="flex flex-wrap items-center justify-between gap-3 text-sm">
                  <div><p className="font-medium text-[var(--bl-text-primary)]">{row.model}</p><p className="text-xs text-[var(--bl-text-secondary)]">{row.provider} · {row.sessionCount} sessions</p></div>
                  <div className="flex items-center gap-2">{Array.from(row.instanceIds).map((id) => <HermesInstanceBadge key={id} instanceId={id} />)}<span className="font-semibold text-[var(--bl-text-primary)]">{formatCompact(row.totalTokens)}</span></div>
                </div>
                <div className="mt-3 h-2 rounded-full bg-[var(--bl-surface-card)]"><div className="h-2 rounded-full bg-[var(--bl-accent)]" style={{ width: `${(row.totalTokens / maxModelTokens) * 100}%` }} /></div>
              </div>
            ))}
          </div>
        </SectionCard>
      </div>

      <SectionCard title="Session usage explorer" subtitle="Filter recent sessions by title/source/model/provider and minimum total tokens." actions={<Badge variant="info"><Filter className="mr-1 h-3 w-3" />{recentSessions.length} rows</Badge>}>
        <div className="mb-4 grid gap-3 md:grid-cols-[1fr_14rem]">
          <input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Filter by model, provider, source, or title…" className="rounded-xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] px-3 py-2 text-sm text-[var(--bl-text-primary)] outline-none focus:border-[var(--bl-accent)]" />
          <input type="number" min={0} step={1000} value={minimumTokens} onChange={(event) => setMinimumTokens(Number(event.target.value) || 0)} aria-label="Minimum tokens" className="rounded-xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] px-3 py-2 text-sm text-[var(--bl-text-primary)] outline-none focus:border-[var(--bl-accent)]" />
        </div>
        <div className="space-y-3">
          {recentSessions.map((session) => (
            <div key={`${session.instanceId}-${session.id}`} className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4">
              <div className="flex flex-wrap items-start justify-between gap-3">
                <div className="min-w-0">
                  <p className="truncate font-medium text-[var(--bl-text-primary)]">{session.title ?? session.id}</p>
                  <p className="text-xs text-[var(--bl-text-secondary)]">{session.model} · {session.provider} · {formatDate(session.endedAt ?? session.startedAt)}</p>
                </div>
                <div className="flex items-center gap-2"><HermesInstanceBadge instanceId={session.instanceId} /><Badge variant="neutral">{formatCompact(session.totalTokens)} tokens</Badge></div>
              </div>
              <dl className="mt-3 grid gap-2 text-sm text-[var(--bl-text-secondary)] md:grid-cols-4">
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Messages</dt><dd>{formatInt(session.messageCount)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Tool calls</dt><dd>{formatInt(session.toolCallCount)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Cost</dt><dd>{formatUsd(session.estimatedCostUsd)}</dd></div>
                <div><dt className="text-xs uppercase tracking-[0.18em] text-[var(--bl-text-tertiary)]">Source</dt><dd>{session.source ?? 'unknown'}</dd></div>
              </dl>
            </div>
          ))}
          {recentSessions.length === 0 ? <p className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4 text-sm text-[var(--bl-text-secondary)]">No sessions matched the current filters.</p> : null}
        </div>
      </SectionCard>

      <SectionCard title="Data contract" subtitle="What is intentionally included and excluded.">
        <div className="grid gap-3 text-sm text-[var(--bl-text-secondary)] md:grid-cols-3">
          <div className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4"><Database className="mb-2 h-5 w-5 text-[var(--bl-accent)]" />Source: local Hermes `state.db` sessions table for Vijay and Bheem.</div>
          <div className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4"><BarChart3 className="mb-2 h-5 w-5 text-[var(--bl-accent)]" />Included: tokens, costs, model/provider, source, titles, dates, messages, and tool-call counts.</div>
          <div className="rounded-2xl border border-[var(--bl-border)] bg-[var(--bl-surface-muted)] p-4"><Filter className="mb-2 h-5 w-5 text-[var(--bl-accent)]" />Excluded: raw prompt/assistant/tool-result message content.</div>
        </div>
      </SectionCard>
    </HermesShell>
  );
}
