import { useState, useEffect, useRef } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import { useDashboard } from '../api/queries/dashboard'
import { useRepos } from '../api/queries/repos'
import { useRecentRuns } from '../api/queries/pipelines'
import { useRecentRepos } from '../hooks/useRecentRepos'
import { Skeleton } from '../ui/Skeleton'
import { RepoAvatar } from '../ui/RepoAvatar'
import type { DashPR, DashIssue, DashRepo, DashRun } from '../api/queries/dashboard'

// ── Utilities ─────────────────────────────────────────────────────────────────

function timeAgo(iso: string): string {
  const diff = Date.now() - new Date(iso).getTime()
  const min = Math.floor(diff / 60_000)
  if (min < 1) return 'just now'
  if (min < 60) return `${min}m ago`
  const hr = Math.floor(min / 60)
  if (hr < 24) return `${hr}h ago`
  const d = Math.floor(hr / 24)
  if (d < 30) return `${d}d ago`
  return `${Math.floor(d / 30)}mo ago`
}

function greeting(username?: string): string {
  const h = new Date().getHours()
  const time = h < 12 ? 'Good morning' : h < 17 ? 'Good afternoon' : 'Good evening'
  return username ? `${time}, ${username}` : time
}

// ── Command palette ────────────────────────────────────────────────────────────

interface CmdResult {
  type: 'repo' | 'pr' | 'issue' | 'run'
  label: string
  sub: string
  href: string
}

function CommandPalette() {
  const { data: dash } = useDashboard()
  const { data: repos = [] } = useRepos()
  const { data: recentRuns = [] } = useRecentRuns(20)
  const [open, setOpen] = useState(false)
  const [q, setQ] = useState('')
  const inputRef = useRef<HTMLInputElement>(null)
  const navigate = useNavigate()

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault()
        setOpen(true)
        setQ('')
        setTimeout(() => inputRef.current?.focus(), 10)
      }
      if (e.key === 'Escape') setOpen(false)
    }
    window.addEventListener('keydown', handler)
    return () => window.removeEventListener('keydown', handler)
  }, [])

  const results: CmdResult[] = q.trim()
    ? [
        ...repos
          .filter(r => r.name.toLowerCase().includes(q.toLowerCase()) || r.description?.toLowerCase().includes(q.toLowerCase()))
          .slice(0, 4)
          .map(r => ({ type: 'repo' as const, label: `${r.ownerName}/${r.name}`, sub: r.description || 'Repository', href: `/repos/${r.ownerName}/${r.name}` })),
        ...(dash?.myOpenPRs ?? [])
          .filter(p => p.title.toLowerCase().includes(q.toLowerCase()))
          .slice(0, 3)
          .map(p => ({ type: 'pr' as const, label: p.title, sub: `${p.ownerName}/${p.repoName} · #${p.id}`, href: `/repos/${p.ownerName}/${p.repoName}/pulls/${p.id}` })),
        ...(dash?.myOpenIssues ?? [])
          .filter(i => i.title.toLowerCase().includes(q.toLowerCase()))
          .slice(0, 3)
          .map(i => ({ type: 'issue' as const, label: i.title, sub: `${i.ownerName}/${i.repoName} · #${i.number}`, href: `/repos/${i.ownerName}/${i.repoName}/issues` })),
        ...recentRuns
          .filter(r =>
            r.repoName.toLowerCase().includes(q.toLowerCase()) ||
            r.triggerRef.toLowerCase().includes(q.toLowerCase()) ||
            r.triggerSha.startsWith(q.toLowerCase()),
          )
          .slice(0, 3)
          .map(r => ({
            type: 'run' as const,
            label: `${r.repoName} #${r.id}`,
            sub: `${r.triggerRef.replace('refs/heads/', '')} · ${r.status} · ${r.triggerSha.slice(0, 7)}`,
            href: `/repos/${r.ownerName}/${r.repoName}/runs/${r.id}`,
          })),
      ]
    : []

  const [sel, setSel] = useState(0)
  useEffect(() => setSel(0), [q])

  function onKey(e: React.KeyboardEvent) {
    if (e.key === 'ArrowDown') { e.preventDefault(); setSel(s => Math.min(s + 1, results.length - 1)) }
    if (e.key === 'ArrowUp') { e.preventDefault(); setSel(s => Math.max(s - 1, 0)) }
    if (e.key === 'Enter' && results[sel]) { navigate(results[sel].href); setOpen(false) }
  }

  const typeIcon = (t: CmdResult['type']) => {
    if (t === 'repo') return (
      <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v8.25A2.25 2.25 0 0 0 4.5 16.5h15a2.25 2.25 0 0 0 2.25-2.25V9A2.25 2.25 0 0 0 19.5 6.75h-1.06l-2.44-2.44a1.5 1.5 0 0 0-1.061-.44H8.69Z" />
      </svg>
    )
    if (t === 'pr') return (
      <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
      </svg>
    )
    if (t === 'run') return (
      <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" />
      </svg>
    )
    return (
      <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
      </svg>
    )
  }

  if (!open) {
    return (
      <button onClick={() => { setOpen(true); setTimeout(() => inputRef.current?.focus(), 10) }}
        className="w-full flex items-center gap-2.5 px-3 py-2.5 border border-[var(--c-border)] rounded-lg bg-[var(--c-surface)] text-[var(--c-muted)] text-sm hover:border-[var(--c-brand-focus)] hover:bg-[var(--c-surface-muted)] transition-colors group">
        <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
        </svg>
        <span className="flex-1 text-left">Search repos, PRs, issues, pipelines…</span>
        <kbd className="hidden sm:inline-flex items-center gap-0.5 px-1.5 py-0.5 text-[10px] font-mono border border-[var(--c-border)] rounded text-[var(--c-subtle)] group-hover:border-[var(--c-brand-focus)]">
          <span>⌘</span><span>K</span>
        </kbd>
      </button>
    )
  }

  return (
    <div className="fixed inset-0 z-50 flex items-start justify-center pt-[15vh] bg-black/40 backdrop-blur-sm" onClick={() => setOpen(false)}>
      <div className="w-full max-w-xl mx-4 bg-[var(--c-surface)] border border-[var(--c-border)] rounded-xl shadow-2xl overflow-hidden" onClick={e => e.stopPropagation()}>
        <div className="flex items-center gap-2.5 px-4 py-3 border-b border-[var(--c-border)]">
          <svg width="16" height="16" fill="none" stroke="var(--c-muted)" strokeWidth="2" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
          </svg>
          <input ref={inputRef} value={q} onChange={e => setQ(e.target.value)} onKeyDown={onKey}
            placeholder="Search repos, PRs, issues, pipelines…"
            className="flex-1 bg-transparent text-sm text-[var(--c-text)] placeholder:text-[var(--c-muted)] focus:outline-none" />
          <kbd className="text-[10px] font-mono text-[var(--c-subtle)] border border-[var(--c-border)] rounded px-1.5 py-0.5">esc</kbd>
        </div>
        {results.length > 0 ? (
          <ul className="max-h-72 overflow-y-auto py-1">
            {results.map((res, i) => (
              <li key={res.href}>
                <Link to={res.href} onClick={() => setOpen(false)}
                  className={`flex items-center gap-3 px-4 py-2.5 transition-colors ${i === sel ? 'bg-[var(--c-brand-tint)] text-[var(--c-brand)]' : 'text-[var(--c-text)] hover:bg-[var(--c-surface-muted)]'}`}>
                  <span className={i === sel ? 'text-[var(--c-brand)]' : 'text-[var(--c-muted)]'}>{typeIcon(res.type)}</span>
                  <span className="flex-1 min-w-0">
                    <span className="text-sm font-medium truncate block">{res.label}</span>
                    <span className="text-xs text-[var(--c-muted)] truncate block">{res.sub}</span>
                  </span>
                </Link>
              </li>
            ))}
          </ul>
        ) : q ? (
          <div className="px-4 py-6 text-center text-sm text-[var(--c-muted)]">No results for "{q}"</div>
        ) : (
          <div className="px-4 py-3">
            <p className="text-[10px] font-semibold uppercase tracking-wider text-[var(--c-muted)] mb-2">Quick navigate</p>
            <div className="flex flex-wrap gap-2">
              {[
                { label: 'My repos', href: '/repos' },
                { label: 'Open PRs', href: '/pulls' },
                { label: 'Pipelines', href: '/pipelines' },
                { label: 'Issues', href: '/issues' },
                { label: 'Explore', href: '/explore' },
                { label: 'Settings', href: '/settings' },
              ].map(link => (
                <Link key={link.href} to={link.href} onClick={() => setOpen(false)}
                  className="px-2.5 py-1 text-xs rounded-md bg-[var(--c-surface-muted)] border border-[var(--c-border)] text-[var(--c-text)] hover:border-[var(--c-brand-focus)] hover:text-[var(--c-brand)] transition-colors">
                  {link.label}
                </Link>
              ))}
            </div>
          </div>
        )}
        <div className="px-4 py-2 border-t border-[var(--c-border)] flex items-center gap-4 text-[10px] text-[var(--c-subtle)]">
          <span className="flex items-center gap-1"><kbd className="font-mono">↑↓</kbd> navigate</span>
          <span className="flex items-center gap-1"><kbd className="font-mono">↵</kbd> open</span>
          <span className="flex items-center gap-1"><kbd className="font-mono">esc</kbd> close</span>
        </div>
      </div>
    </div>
  )
}

// ── Stat pill ─────────────────────────────────────────────────────────────────

function StatPill({ label, value, to, warn }: { label: string; value: number; to: string; warn?: boolean }) {
  return (
    <Link to={to} className="flex flex-col items-center px-4 py-2.5 rounded-lg border border-[var(--c-border)] bg-[var(--c-surface)] hover:border-[var(--c-brand-focus)] hover:bg-[var(--c-surface-muted)] transition-colors group min-w-[72px]">
      <span className={`text-xl font-bold tabular-nums ${warn && value > 0 ? 'text-[var(--c-warning)]' : 'text-[var(--c-text)]'} group-hover:text-[var(--c-brand)] transition-colors`}>{value}</span>
      <span className="text-[10px] text-[var(--c-muted)] mt-0.5 whitespace-nowrap">{label}</span>
    </Link>
  )
}

// ── Section wrapper ───────────────────────────────────────────────────────────

function Section({ title, count, icon, children, action }: {
  title: string; count?: number; icon: React.ReactNode; children: React.ReactNode; action?: React.ReactNode
}) {
  return (
    <section>
      <div className="flex items-center justify-between mb-2.5">
        <h2 className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-[var(--c-muted)]">
          <span className="text-[var(--c-muted)]">{icon}</span>
          {title}
          {count !== undefined && count > 0 && (
            <span className="px-1.5 py-0.5 text-[10px] font-bold rounded-full bg-[var(--c-brand)] text-white leading-none">{count}</span>
          )}
        </h2>
        {action}
      </div>
      {children}
    </section>
  )
}

// ── PR row ────────────────────────────────────────────────────────────────────

function PRRow({ pr, badge }: { pr: DashPR; badge?: React.ReactNode }) {
  return (
    <Link to={`/repos/${pr.ownerName}/${pr.repoName}/pulls/${pr.id}`}
      className="flex items-start gap-3 px-3.5 py-2.5 hover:bg-[var(--c-surface-muted)] transition-colors group">
      <svg className="mt-0.5 shrink-0 text-[var(--c-success)]" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
      </svg>
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2 flex-wrap">
          <span className="text-sm font-medium text-[var(--c-text)] group-hover:text-[var(--c-brand)] truncate transition-colors">{pr.title}</span>
          {badge}
        </div>
        <p className="text-xs text-[var(--c-muted)] mt-0.5">
          <span className="font-mono">{pr.ownerName}/{pr.repoName}</span>
          {' · '}
          <span className="font-mono text-[var(--c-muted)]">{pr.sourceBranch}</span>
          {' → '}
          <span className="font-mono text-[var(--c-muted)]">{pr.targetBranch}</span>
          {' · '}
          {timeAgo(pr.updatedAt)}
        </p>
      </div>
    </Link>
  )
}

// ── Issue row ─────────────────────────────────────────────────────────────────

function IssueRow({ issue }: { issue: DashIssue }) {
  return (
    <Link to={`/repos/${issue.ownerName}/${issue.repoName}/issues`}
      className="flex items-start gap-3 px-3.5 py-2.5 hover:bg-[var(--c-surface-muted)] transition-colors group">
      <svg className="mt-0.5 shrink-0 text-[var(--c-brand)]" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
      </svg>
      <div className="flex-1 min-w-0">
        <span className="text-sm font-medium text-[var(--c-text)] group-hover:text-[var(--c-brand)] truncate block transition-colors">{issue.title}</span>
        <p className="text-xs text-[var(--c-muted)] mt-0.5">
          <span className="font-mono">{issue.ownerName}/{issue.repoName}</span>
          {' · '}#{issue.number}
          {' · '}
          {timeAgo(issue.updatedAt)}
        </p>
      </div>
    </Link>
  )
}

// ── Repo workspace card ───────────────────────────────────────────────────────

function RepoCard({ repo }: { repo: DashRepo }) {
  return (
    <Link to={`/repos/${repo.ownerName}/${repo.name}`}
      className="flex items-center gap-3 px-3.5 py-2.5 hover:bg-[var(--c-surface-muted)] transition-colors group">
      <RepoAvatar ownerName={repo.ownerName} name={repo.name} avatarUrl={repo.avatarUrl} size={28} />
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-1.5">
          <span className="text-sm font-medium text-[var(--c-text)] group-hover:text-[var(--c-brand)] truncate transition-colors">{repo.name}</span>
          {repo.isPrivate && (
            <span className="text-[9px] font-semibold uppercase tracking-wider border border-[var(--c-border)] text-[var(--c-muted)] px-1 py-px rounded shrink-0">private</span>
          )}
        </div>
        <div className="flex items-center gap-2.5 mt-0.5">
          {repo.openPrCount > 0 && (
            <span className="flex items-center gap-0.5 text-[10px] text-[var(--c-muted)]">
              <svg width="9" height="9" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
              </svg>
              {repo.openPrCount} PR{repo.openPrCount !== 1 ? 's' : ''}
            </span>
          )}
          {repo.openIssueCount > 0 && (
            <span className="flex items-center gap-0.5 text-[10px] text-[var(--c-muted)]">
              <svg width="9" height="9" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
              </svg>
              {repo.openIssueCount}
            </span>
          )}
          <span className="text-[10px] text-[var(--c-subtle)]">{timeAgo(repo.updatedAt)}</span>
        </div>
      </div>
      <svg className="shrink-0 text-[var(--c-border)] group-hover:text-[var(--c-brand)] transition-colors" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
      </svg>
    </Link>
  )
}

// ── CI run row ────────────────────────────────────────────────────────────────

const RUN_DOT: Record<string, string> = {
  queued:    'bg-[var(--c-subtle)]',
  running:   'bg-[var(--c-brand)] animate-pulse',
  succeeded: 'bg-[var(--c-success)]',
  failed:    'bg-[var(--c-danger)]',
  cancelled: 'bg-[var(--c-subtle)]',
}

const RUN_LABEL: Record<string, string> = {
  queued:    'Queued',
  running:   'Running',
  succeeded: 'Passed',
  failed:    'Failed',
  cancelled: 'Cancelled',
}

function CIRunRow({ run }: { run: DashRun }) {
  const branch = run.triggerRef.replace('refs/heads/', '').replace('refs/tags/', '')
  const sha = run.triggerSha.slice(0, 7)
  return (
    <Link to={`/repos/${run.ownerName}/${run.repoName}/runs/${run.id}`}
      className="flex items-center gap-2.5 px-3.5 py-2.5 hover:bg-[var(--c-surface-muted)] transition-colors group">
      <span className={`w-1.5 h-1.5 rounded-full shrink-0 ${RUN_DOT[run.status] ?? 'bg-[var(--c-subtle)]'}`} />
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-1.5 flex-wrap">
          <span className="text-sm font-medium text-[var(--c-text)] group-hover:text-[var(--c-brand)] truncate transition-colors">
            {run.repoName}
          </span>
          <span className="text-[10px] font-mono text-[var(--c-muted)]">{branch}</span>
        </div>
        <p className="text-[10px] text-[var(--c-muted)] mt-0.5 font-mono">{sha}</p>
      </div>
      <span className={`text-[10px] font-medium shrink-0 ${run.status === 'failed' ? 'text-[var(--c-danger)]' : run.status === 'running' ? 'text-[var(--c-brand)]' : run.status === 'succeeded' ? 'text-[var(--c-success)]' : 'text-[var(--c-muted)]'}`}>
        {RUN_LABEL[run.status] ?? run.status}
      </span>
    </Link>
  )
}

// ── Empty state ───────────────────────────────────────────────────────────────

function Empty({ message, action }: { message: string; action?: React.ReactNode }) {
  return (
    <div className="px-3.5 py-5 text-center">
      <p className="text-xs text-[var(--c-muted)]">{message}</p>
      {action && <div className="mt-2">{action}</div>}
    </div>
  )
}

// ── Panel wrapper ─────────────────────────────────────────────────────────────

function Panel({ children, className = '' }: { children: React.ReactNode; className?: string }) {
  return (
    <div className={`border border-[var(--c-border)] rounded-lg bg-[var(--c-surface)] overflow-hidden divide-y divide-[var(--c-border)] ${className}`}>
      {children}
    </div>
  )
}

// ── Skeleton states ───────────────────────────────────────────────────────────

function PanelSkeleton({ rows = 3 }: { rows?: number }) {
  return (
    <div className="border border-[var(--c-border)] rounded-lg bg-[var(--c-surface)] divide-y divide-[var(--c-border)]">
      {Array.from({ length: rows }).map((_, i) => (
        <div key={i} className="flex items-center gap-3 px-3.5 py-2.5">
          <Skeleton className="w-3.5 h-3.5 rounded-full shrink-0" />
          <div className="flex-1 space-y-1.5">
            <Skeleton className="h-3.5 w-3/4 rounded" />
            <Skeleton className="h-2.5 w-1/2 rounded" />
          </div>
        </div>
      ))}
    </div>
  )
}

// ── Main page ─────────────────────────────────────────────────────────────────

export default function DashboardPage() {
  const { user } = useAuth()
  const { data: dash, isLoading } = useDashboard()
  const { repos: recentRepos } = useRecentRepos()

  const stats = dash?.stats
  const needsAttention = (stats?.reviewQueue ?? 0) > 0

  return (
    <div className="max-w-5xl mx-auto px-4 md:px-6 py-5 space-y-5">
      <CommandPalette />

      {/* Greeting + stats */}
      <div className="flex flex-col sm:flex-row sm:items-center gap-4 justify-between">
        <div>
          <h1 className="text-lg font-semibold text-[var(--c-text)]">{greeting(user?.username)}</h1>
          <p className="text-xs text-[var(--c-muted)] mt-0.5">
            {new Date().toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}
          </p>
        </div>

        <div className="flex items-center gap-2">
          {isLoading ? (
            <>
              <Skeleton className="h-14 w-20 rounded-lg" />
              <Skeleton className="h-14 w-20 rounded-lg" />
              <Skeleton className="h-14 w-20 rounded-lg" />
              <Skeleton className="h-14 w-20 rounded-lg" />
            </>
          ) : (
            <>
              <StatPill label="Repos" value={stats?.repoCount ?? 0} to="/repos" />
              <StatPill label="My PRs" value={stats?.openPRs ?? 0} to="/pulls" />
              <StatPill label="Reviews" value={stats?.reviewQueue ?? 0} to="/pulls" warn />
              <StatPill label="Issues" value={stats?.openIssues ?? 0} to="/issues" />
            </>
          )}
        </div>
      </div>

      {/* Main grid */}
      <div className="grid grid-cols-1 lg:grid-cols-5 gap-4">

        {/* Left column (wider) */}
        <div className="lg:col-span-3 space-y-4">

          {/* Needs attention */}
          {(isLoading || needsAttention || (dash?.reviewQueue?.length ?? 0) > 0) && (
            <Section
              title="Needs attention"
              count={dash?.reviewQueue.length}
              icon={
                <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
                </svg>
              }
            >
              {isLoading ? <PanelSkeleton rows={2} /> : (
                <Panel>
                  {dash!.reviewQueue.length === 0 ? (
                    <Empty message="No PRs awaiting your review." />
                  ) : (
                    dash!.reviewQueue.map(pr => (
                      <PRRow key={pr.id} pr={pr} badge={
                        <span className="text-[9px] font-semibold uppercase tracking-wider px-1.5 py-px rounded-full bg-[var(--c-warning)]/15 text-[var(--c-warning)] border border-[var(--c-warning)]/30 shrink-0">
                          Review requested
                        </span>
                      } />
                    ))
                  )}
                </Panel>
              )}
            </Section>
          )}

          {/* My open PRs */}
          <Section
            title="My pull requests"
            count={dash?.myOpenPRs.length}
            icon={
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
              </svg>
            }
            action={
              <Link to="/pulls" className="text-[10px] text-[var(--c-brand)] hover:underline">View all</Link>
            }
          >
            {isLoading ? <PanelSkeleton rows={3} /> : (
              <Panel>
                {!dash?.myOpenPRs.length ? (
                  <Empty
                    message="No open pull requests."
                    action={<Link to="/repos" className="text-xs text-[var(--c-brand)] hover:underline">Browse your repos →</Link>}
                  />
                ) : (
                  dash.myOpenPRs.slice(0, 6).map(pr => <PRRow key={pr.id} pr={pr} />)
                )}
              </Panel>
            )}
          </Section>

          {/* Open issues */}
          <Section
            title="My open issues"
            count={dash?.myOpenIssues.length}
            icon={
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
              </svg>
            }
          >
            {isLoading ? <PanelSkeleton rows={3} /> : (
              <Panel>
                {!dash?.myOpenIssues.length ? (
                  <Empty message="No open issues authored by you." />
                ) : (
                  dash.myOpenIssues.slice(0, 6).map(i => <IssueRow key={i.id} issue={i} />)
                )}
              </Panel>
            )}
          </Section>
        </div>

        {/* Right column */}
        <div className="lg:col-span-2 space-y-4">

          {/* Active workspaces */}
          <Section
            title="Workspaces"
            icon={
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 0 0-1.883 2.542l.857 6a2.25 2.25 0 0 0 2.227 1.932H19.05a2.25 2.25 0 0 0 2.227-1.932l.857-6a2.25 2.25 0 0 0-1.883-2.542m-16.5 0V6A2.25 2.25 0 0 1 6 3.75h3.879a1.5 1.5 0 0 1 1.06.44l2.122 2.12a1.5 1.5 0 0 0 1.06.44H18A2.25 2.25 0 0 1 20.25 9v.776" />
              </svg>
            }
            action={
              <Link to="/repos" className="text-[10px] text-[var(--c-brand)] hover:underline">All repos</Link>
            }
          >
            {isLoading ? <PanelSkeleton rows={4} /> : (
              <Panel>
                {!dash?.repos.length ? (
                  <Empty
                    message="No repositories yet."
                    action={<Link to="/repos" className="text-xs text-[var(--c-brand)] hover:underline">Create a repository →</Link>}
                  />
                ) : (
                  (() => {
                    // Prioritise recently visited, then fall back to API order
                    const recentNames = new Set(recentRepos.map(r => r.name))
                    const prioritised = [
                      ...dash.repos.filter(r => recentNames.has(r.name)),
                      ...dash.repos.filter(r => !recentNames.has(r.name)),
                    ].slice(0, 7)
                    return prioritised.map(r => <RepoCard key={r.id} repo={r} />)
                  })()
                )}
              </Panel>
            )}
          </Section>

          {/* CI / CD — live recent runs */}
          <Section
            title="CI / CD"
            icon={
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" />
              </svg>
            }
            action={
              <Link to="/pipelines" className="text-[10px] text-[var(--c-brand)] hover:underline">All runs</Link>
            }
          >
            {isLoading ? <PanelSkeleton rows={3} /> : (
              <Panel>
                {!dash?.recentRuns?.length ? (
                  <Empty
                    message="No pipeline runs yet."
                    action={
                      <p className="text-[10px] text-[var(--c-muted)] mt-1">
                        Push to a repo with a <code className="font-mono bg-[var(--c-surface-muted)] px-1 rounded">.forgebucket/workflows/</code> file.
                      </p>
                    }
                  />
                ) : (
                  dash.recentRuns.map(run => <CIRunRow key={run.id} run={run} />)
                )}
              </Panel>
            )}
          </Section>

          {/* Quick actions */}
          <Section
            title="Quick actions"
            icon={
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2.5" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
              </svg>
            }
          >
            <Panel>
              {[
                { label: 'New repository', href: '/repos', icon: <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg> },
                { label: 'Import repository', href: '/repos/import', icon: <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></svg> },
                { label: 'Explore projects', href: '/explore', icon: <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" /></svg> },
                { label: 'Account settings', href: '/settings', icon: <svg width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" /><path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg> },
              ].map(a => (
                <Link key={a.href} to={a.href}
                  className="flex items-center gap-2.5 px-3.5 py-2.5 text-sm text-[var(--c-text)] hover:bg-[var(--c-surface-muted)] hover:text-[var(--c-brand)] transition-colors group">
                  <span className="text-[var(--c-muted)] group-hover:text-[var(--c-brand)] transition-colors">{a.icon}</span>
                  {a.label}
                </Link>
              ))}
            </Panel>
          </Section>

        </div>
      </div>

      {/* Empty state hero — shown only when user has no repos at all */}
      {!isLoading && dash?.repos.length === 0 && (
        <div className="rounded-lg border border-dashed border-[var(--c-border)] bg-[var(--c-surface)] p-10 text-center space-y-3">
          <div className="w-12 h-12 rounded-full bg-[var(--c-brand-tint)] flex items-center justify-center mx-auto">
            <svg width="24" height="24" fill="none" stroke="var(--c-brand)" strokeWidth="1.5" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v8.25A2.25 2.25 0 0 0 4.5 16.5h15a2.25 2.25 0 0 0 2.25-2.25V9A2.25 2.25 0 0 0 19.5 6.75h-1.06l-2.44-2.44a1.5 1.5 0 0 0-1.061-.44H8.69Z" />
            </svg>
          </div>
          <div>
            <h2 className="text-base font-semibold text-[var(--c-text)]">Welcome to ForgeBucket{user?.username ? `, ${user.username}` : ''}</h2>
            <p className="text-sm text-[var(--c-muted)] mt-1 max-w-sm mx-auto">
              Create your first repository to get started. Your operational dashboard will populate as you work.
            </p>
          </div>
          <div className="flex items-center justify-center gap-3">
            <Link to="/repos" className="px-4 py-2 rounded-lg bg-[var(--c-brand)] text-white text-sm font-medium hover:bg-[var(--c-brand-hover)]">
              Create repository
            </Link>
            <Link to="/explore" className="px-4 py-2 rounded-lg border border-[var(--c-border)] text-sm text-[var(--c-text)] font-medium hover:bg-[var(--c-surface-muted)]">
              Explore
            </Link>
          </div>
        </div>
      )}
    </div>
  )
}
