import { Link } from '@tanstack/react-router';
import { useLiveQuery } from 'dexie-react-hooks';
import {
  Brain, Users, Swords, ScrollText, VenetianMask, Target, Map, CalendarDays, Library, Hammer, Dice5, Monitor,
  ChevronRight, Shield, CheckCheck, Skull, Handshake,
} from 'lucide-react';
import type { Campaign, Character, Npc, Quest, DiceRoll } from '@/lib/schemas';
import { diceRepo } from '@/lib/db/repositories';
import { getSystem } from '@/lib/rules';
import { cn } from '@/lib/cn';
import { useCharacters } from '@/features/characters/hooks';
import { useEncounters } from '@/features/combat/hooks';
import { useNotes, useNpcs, useQuests, useCalendar } from './hooks';
import { Page, RequireCampaign } from '@/components/ui/Page';
import { Meter, Badge, Avatar } from '@/components/ui/Codex';

export function DashboardPage() {
  return <RequireCampaign>{(c) => <Dashboard campaign={c} />}</RequireCampaign>;
}

type NavIcon = React.ComponentType<{ size?: number; className?: string; 'aria-hidden'?: boolean | 'true' | 'false' }>;
const LINKS: { to: string; label: string; icon: NavIcon }[] = [
  { to: '/assistant', label: 'Assistant', icon: Brain },
  { to: '/characters', label: 'Characters', icon: Users },
  { to: '/combat', label: 'Combat', icon: Swords },
  { to: '/notes', label: 'Notes & Wiki', icon: ScrollText },
  { to: '/npcs', label: 'NPCs', icon: VenetianMask },
  { to: '/quests', label: 'Quests', icon: Target },
  { to: '/maps', label: 'Maps', icon: Map },
  { to: '/calendar', label: 'Calendar', icon: CalendarDays },
  { to: '/compendium', label: 'Compendium', icon: Library },
  { to: '/homebrew', label: 'Homebrew', icon: Hammer },
  { to: '/dice', label: 'Dice', icon: Dice5 },
  { to: '/play', label: 'Player View', icon: Monitor },
];

function Dashboard({ campaign }: { campaign: Campaign }) {
  const characters = useCharacters(campaign.id);
  const encounters = useEncounters(campaign.id);
  const notes = useNotes(campaign.id);
  const npcs = useNpcs(campaign.id);
  const quests = useQuests(campaign.id);
  const calendar = useCalendar(campaign.id);
  const rolls = useLiveQuery(() => diceRepo.recent(campaign.id, 8), [campaign.id], []);

  const sys = getSystem(campaign.system);
  const pcs = characters.filter((c) => c.kind === 'pc');
  const activeQuests = quests.filter((q) => q.status === 'active').length;

  return (
    <Page>
      {/* Editorial hero */}
      <section className="paper-grain mb-6 overflow-hidden rounded-xl border border-line bg-panel">
        <div className="px-7 py-7 sm:px-9">
          <div className="font-display text-sm italic text-accent">
            {sys.label}
            {calendar ? ` · in-world day ${calendar.currentDay}` : ''}
          </div>
          <h1 className="mt-1 font-display text-4xl font-semibold leading-[1.04] tracking-tight text-ink">
            {campaign.name}
          </h1>
          {campaign.description && (
            <p className="mt-2.5 max-w-2xl font-display text-base italic text-muted">
              {campaign.description}
            </p>
          )}
        </div>
        <hr className="gilt-rule" />
      </section>

      {/* Quick stats */}
      <div className="mb-6 grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5">
        <Stat label="Characters" value={characters.length} />
        <Stat label="Encounters" value={encounters.length} />
        <Stat label="Active quests" value={activeQuests} />
        <Stat label="NPCs" value={npcs.length} />
        <Stat label="Notes" value={notes.length} />
      </div>

      <div className="grid gap-6 lg:grid-cols-[1fr_320px]">
        {/* Navigation cards */}
        <section>
          <h2 className="smallcaps mb-3">Jump to</h2>
          <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
            {LINKS.map((l) => (
              <Link
                key={l.to}
                to={l.to}
                className="flex flex-col items-center gap-1 rounded-xl border border-line bg-panel p-4 text-center transition-colors hover:border-accent/60 hover:bg-accent-glow"
              >
                <l.icon size={24} className="text-muted" aria-hidden />
                <span className="text-sm text-ink">{l.label}</span>
              </Link>
            ))}
          </div>

          {/* Party overview */}
          <div className="mb-3 mt-7 flex items-center justify-between">
            <h2 className="smallcaps">Party</h2>
            <Link to="/characters" className="flex items-center gap-1 text-xs text-muted hover:text-accent-deep">
              Manage <ChevronRight size={14} aria-hidden />
            </Link>
          </div>
          {pcs.length === 0 ? (
            <p className="text-sm text-muted">No player characters yet.</p>
          ) : (
            <div className="grid gap-2 sm:grid-cols-2">
              {pcs.map((c) => (
                <PartyRow key={c.id} c={c} sys={sys} />
              ))}
            </div>
          )}

          {/* Cast & threats */}
          {npcs.length > 0 && (
            <>
              <h2 className="smallcaps mb-3 mt-7">Cast &amp; Threats</h2>
              <div className="grid gap-2 sm:grid-cols-2">
                {npcs.slice(0, 6).map((n) => (
                  <ThreatRow key={n.id} n={n} />
                ))}
              </div>
            </>
          )}
        </section>

        {/* Side column: quests + recent rolls */}
        <aside className="space-y-6">
          <div>
            <h2 className="smallcaps mb-3">Quest Log</h2>
            {quests.length === 0 ? (
              <p className="text-sm text-muted">No quests yet.</p>
            ) : (
              <div className="paper-grain space-y-3 rounded-xl border border-line bg-panel p-4">
                {quests.slice(0, 6).map((q) => (
                  <QuestRow key={q.id} q={q} />
                ))}
              </div>
            )}
          </div>

          <div>
            <div className="mb-3 flex items-center justify-between">
              <h2 className="smallcaps">Recent rolls</h2>
              <Link to="/dice" className="flex items-center gap-1 text-xs text-muted hover:text-accent-deep">
                Open tray <ChevronRight size={14} aria-hidden />
              </Link>
            </div>
            {rolls.length === 0 ? (
              <p className="text-sm text-muted">No rolls yet.</p>
            ) : (
              <ul className="space-y-1.5">
                {rolls.map((r) => (
                  <RollRow key={r.id} r={r} />
                ))}
              </ul>
            )}
          </div>
        </aside>
      </div>
    </Page>
  );
}

function PartyRow({ c, sys }: { c: Character; sys: ReturnType<typeof getSystem> }) {
  const ac = sys.baseArmorClass({ level: c.level, abilities: c.abilities, armorBonus: c.armorBonus, ...(c.equippedArmor ? { equippedArmor: c.equippedArmor } : {}) });
  const ratio = c.hp.max > 0 ? c.hp.current / c.hp.max : 0;
  const tone = ratio < 0.35 ? 'var(--app-danger)' : undefined;
  return (
    <Link
      to="/characters/$characterId"
      params={{ characterId: c.id }}
      className="flex items-center gap-3 rounded-xl border border-line bg-panel px-3 py-2.5 transition-colors hover:border-accent/50 hover:bg-accent-glow"
    >
      <Avatar name={c.name} size={42} />
      <div className="min-w-0 flex-1">
        <div className="flex items-baseline justify-between gap-2">
          <span className="truncate font-display text-sm font-semibold text-ink">{c.name}</span>
          <span className="shrink-0 font-mono text-xs text-faint">{c.hp.current}/{c.hp.max}</span>
        </div>
        <div className="mt-0.5 truncate text-xs text-faint">
          Lv {c.level} {[c.ancestry, c.className].filter(Boolean).join(' ')}
        </div>
        <div className="mt-1.5">
          <Meter value={c.hp.current} max={c.hp.max} height={5} {...(tone ? { tone } : {})} />
        </div>
      </div>
      <div className="flex w-9 shrink-0 flex-col items-center">
        <Shield size={15} className="text-muted" aria-hidden />
        <span className="font-mono text-sm font-semibold text-ink">{ac}</span>
      </div>
    </Link>
  );
}

const NPC_DISPOSITION: Record<Npc['status'], { tone: 'ember' | 'verdigris' | 'default'; label: string; Icon: typeof Skull }> = {
  dead: { tone: 'ember', label: 'Hostile', Icon: Skull },
  alive: { tone: 'verdigris', label: 'Friendly', Icon: Handshake },
  unknown: { tone: 'default', label: 'Unknown', Icon: VenetianMask },
};

function ThreatRow({ n }: { n: Npc }) {
  const d = NPC_DISPOSITION[n.status];
  const Icon = d.Icon;
  return (
    <Link
      to="/npcs"
      className="flex items-center gap-3 rounded-xl border border-line bg-panel px-3 py-2.5 transition-colors hover:border-accent/50 hover:bg-accent-glow"
    >
      <span className="grid size-8 shrink-0 place-items-center rounded-lg border border-line bg-surface-2 text-muted">
        <Icon size={16} aria-hidden />
      </span>
      <div className="min-w-0 flex-1">
        <div className="truncate font-display text-sm font-semibold text-ink">{n.name}</div>
        <div className="truncate text-xs text-faint">
          {[n.role, n.location].filter(Boolean).join(' · ') || '—'}
        </div>
      </div>
      <Badge tone={d.tone}>{d.label}</Badge>
    </Link>
  );
}

function QuestRow({ q }: { q: Quest }) {
  const done = q.status === 'completed';
  return (
    <div className={cn(done && 'opacity-55')}>
      <div className="flex items-center justify-between gap-2">
        <span className="flex min-w-0 items-center gap-2">
          {done ? (
            <CheckCheck size={16} className="shrink-0 text-accent-deep" aria-hidden />
          ) : (
            <ScrollText size={16} className="shrink-0 text-muted" aria-hidden />
          )}
          <span className={cn('truncate font-display text-sm font-semibold text-ink', done && 'line-through')}>
            {q.title}
          </span>
        </span>
        {q.objectives.length > 0 && (
          <span className="flex shrink-0 items-center gap-1">
            {q.objectives.slice(0, 6).map((o) => (
              <span
                key={o.id}
                className={cn('size-[7px] rounded-full', o.done ? 'bg-accent' : 'bg-line-strong')}
              />
            ))}
          </span>
        )}
      </div>
    </div>
  );
}

function RollRow({ r }: { r: DiceRoll }) {
  return (
    <li className="flex items-center gap-3 rounded-xl border border-line bg-panel px-3 py-2 text-sm">
      <span className="h-6 w-[3px] shrink-0 rounded-sm bg-accent" aria-hidden />
      <span className="min-w-0 flex-1 truncate text-muted">
        {r.label ? `${r.label}: ` : ''}
        <span className="font-mono">{r.expression}</span>
      </span>
      <span className="font-display font-semibold text-ink">{r.total}</span>
    </li>
  );
}

function Stat({ label, value }: { label: string; value: number }) {
  return (
    <div className="rounded-xl border border-line bg-panel p-4 text-center">
      <div className="font-mono text-3xl font-bold text-accent-deep">{value}</div>
      <div className="smallcaps mt-1" style={{ fontSize: 10 }}>{label}</div>
    </div>
  );
}
