import { useState, useMemo } from 'react'
import { createFileRoute, useNavigate, useSearch, Link } from '@tanstack/react-router'
import { trpc } from '@/lib/trpc'
import { useLiveUpdates } from '@/hooks'
import type { LiveUpdateRule } from '@/hooks'
import { Card, CardContent } from '@/components/ui/card'
import { CompactionEventsDialog } from '@/components/radar/CompactionEventsDialog'
import { SubagentSpawnsDialog } from '@/components/radar/SubagentSpawnsDialog'
import { QuestionsAskedDialog } from '@/components/radar/QuestionsAskedDialog'
import { InterAgentMessagesDialog } from '@/components/radar/InterAgentMessagesDialog'

type TimeRange = '1h' | '6h' | '24h' | '7d' | 'all'
type StatusFilter = 'all' | 'running' | 'completed' | 'crashed'
type ModeFilter = 'all' | 'execute' | 'discuss' | 'plan' | 'detail' | 'refine' | 'chat' | 'errand'
type SortColumn =
  | 'name'
  | 'mode'
  | 'status'
  | 'initiative'
  | 'task'
  | 'started'
  | 'questions'
  | 'messages'
  | 'subagents'
  | 'compactions'

const VALID_TIME_RANGES: TimeRange[] = ['1h', '6h', '24h', '7d', 'all']
const VALID_STATUSES: StatusFilter[] = ['all', 'running', 'completed', 'crashed']
const VALID_MODES: ModeFilter[] = [
  'all',
  'execute',
  'discuss',
  'plan',
  'detail',
  'refine',
  'chat',
  'errand',
]

export const Route = createFileRoute('/radar')({
  component: RadarPage,
  validateSearch: (search: Record<string, unknown>) => ({
    timeRange: VALID_TIME_RANGES.includes(search.timeRange as TimeRange)
      ? (search.timeRange as TimeRange)
      : '24h',
    status: VALID_STATUSES.includes(search.status as StatusFilter)
      ? (search.status as StatusFilter)
      : 'all',
    initiativeId: typeof search.initiativeId === 'string' ? search.initiativeId : undefined,
    mode: VALID_MODES.includes(search.mode as ModeFilter) ? (search.mode as ModeFilter) : 'all',
  }),
})

const RADAR_LIVE_UPDATE_RULES: LiveUpdateRule[] = [
  { prefix: 'agent:waiting', invalidate: ['agent'] },
  { prefix: 'conversation:created', invalidate: ['agent'] },
  { prefix: 'agent:stopped', invalidate: ['agent'] },
  { prefix: 'agent:crashed', invalidate: ['agent'] },
]

export function RadarPage() {
  const { timeRange, status, initiativeId, mode } = useSearch({ from: '/radar' }) as {
    timeRange: TimeRange
    status: StatusFilter
    initiativeId: string | undefined
    mode: ModeFilter
  }
  const navigate = useNavigate()

  useLiveUpdates(RADAR_LIVE_UPDATE_RULES)

  const { data: agents = [], isLoading } = trpc.agent.listForRadar.useQuery({
    timeRange,
    status: status === 'all' ? undefined : status,
    initiativeId: initiativeId ?? undefined,
    mode: mode === 'all' ? undefined : mode,
  })

  const { data: initiatives = [] } = trpc.listInitiatives.useQuery()

  type DrilldownType = 'questions' | 'messages' | 'subagents' | 'compactions'

  const [drilldown, setDrilldown] = useState<{
    type: DrilldownType
    agentId: string
    agentName: string
  } | null>(null)

  const [sortState, setSortState] = useState<{ column: SortColumn; direction: 'asc' | 'desc' }>({
    column: 'started',
    direction: 'desc',
  })

  function handleSort(column: SortColumn) {
    setSortState((prev) =>
      prev.column === column
        ? { column, direction: prev.direction === 'asc' ? 'desc' : 'asc' }
        : { column, direction: 'asc' },
    )
  }

  const sortedAgents = useMemo(() => {
    return [...agents].sort((a, b) => {
      let cmp = 0
      switch (sortState.column) {
        case 'name':
          cmp = a.name.localeCompare(b.name)
          break
        case 'mode':
          cmp = a.mode.localeCompare(b.mode)
          break
        case 'status':
          cmp = a.status.localeCompare(b.status)
          break
        case 'initiative':
          cmp = (a.initiativeName ?? '').localeCompare(b.initiativeName ?? '')
          break
        case 'task':
          cmp = (a.taskName ?? '').localeCompare(b.taskName ?? '')
          break
        case 'started':
          cmp = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
          break
        case 'questions':
          cmp = a.questionsCount - b.questionsCount
          break
        case 'messages':
          cmp = a.messagesCount - b.messagesCount
          break
        case 'subagents':
          cmp = a.subagentsCount - b.subagentsCount
          break
        case 'compactions':
          cmp = a.compactionsCount - b.compactionsCount
          break
      }
      return sortState.direction === 'asc' ? cmp : -cmp
    })
  }, [agents, sortState])

  const totalQuestions = agents.reduce((sum, a) => sum + a.questionsCount, 0)
  const totalMessages = agents.reduce((sum, a) => sum + a.messagesCount, 0)
  const totalSubagents = agents.reduce((sum, a) => sum + a.subagentsCount, 0)
  const totalCompactions = agents.reduce((sum, a) => sum + a.compactionsCount, 0)

  function sortIndicator(column: SortColumn) {
    if (sortState.column !== column) return null
    return sortState.direction === 'asc' ? ' ▲' : ' ▼'
  }

  function SortableTh({
    column,
    label,
    className,
  }: {
    column: SortColumn
    label: string
    className?: string
  }) {
    return (
      <th
        className={`cursor-pointer select-none whitespace-nowrap px-3 py-2 text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground hover:text-foreground ${className ?? ''}`}
        onClick={() => handleSort(column)}
      >
        {label}
        {sortIndicator(column)}
      </th>
    )
  }

  const isAgentRunning = drilldown
    ? agents.find((a) => a.id === drilldown.agentId)?.status === 'running'
    : false

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold">Radar</h1>

      {/* Summary stat cards */}
      <div className="grid grid-cols-4 gap-4">
        <Card>
          <CardContent className="pt-6">
            <p className="text-3xl font-bold">{totalQuestions}</p>
            <p className="text-sm text-muted-foreground">Total Questions Asked</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <p className="text-3xl font-bold">{totalMessages}</p>
            <p className="text-sm text-muted-foreground">Total Inter-Agent Messages</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <p className="text-3xl font-bold">{totalSubagents}</p>
            <p className="text-sm text-muted-foreground">Total Subagent Spawns</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <p className="text-3xl font-bold">{totalCompactions}</p>
            <p className="text-sm text-muted-foreground">Total Compaction Events</p>
          </CardContent>
        </Card>
      </div>

      {/* Filter bar */}
      <div className="flex gap-4 items-center">
        <select
          value={timeRange}
          onChange={(e) => {
            const val = e.target.value as TimeRange
            navigate({ search: (prev) => ({ ...prev, timeRange: val }) })
          }}
        >
          <option value="1h">Last 1h</option>
          <option value="6h">Last 6h</option>
          <option value="24h">Last 24h</option>
          <option value="7d">Last 7d</option>
          <option value="all">All time</option>
        </select>

        <select
          value={status}
          onChange={(e) => {
            const val = e.target.value as StatusFilter
            navigate({ search: (prev) => ({ ...prev, status: val }) })
          }}
        >
          <option value="all">All</option>
          <option value="running">Running</option>
          <option value="completed">Completed</option>
          <option value="crashed">Crashed</option>
        </select>

        <select
          value={initiativeId ?? ''}
          onChange={(e) => {
            const val = e.target.value
            navigate({
              search: (prev) => ({ ...prev, initiativeId: val === '' ? undefined : val }),
            })
          }}
        >
          <option value="">All Initiatives</option>
          {initiatives.map((ini: { id: string; name: string }) => (
            <option key={ini.id} value={ini.id}>
              {ini.name}
            </option>
          ))}
        </select>

        <select
          value={mode}
          onChange={(e) => {
            const val = e.target.value as ModeFilter
            navigate({ search: (prev) => ({ ...prev, mode: val }) })
          }}
        >
          <option value="all">All</option>
          <option value="execute">Execute</option>
          <option value="discuss">Discuss</option>
          <option value="plan">Plan</option>
          <option value="detail">Detail</option>
          <option value="refine">Refine</option>
          <option value="chat">Chat</option>
          <option value="errand">Errand</option>
        </select>
      </div>

      {/* Empty state */}
      {!isLoading && agents.length === 0 && (
        <p className="text-center text-muted-foreground">No agent activity in this time period</p>
      )}

      {/* Agent activity table */}
      {(isLoading || agents.length > 0) && (
        <table className="w-full border-collapse text-sm">
          <thead>
            <tr className="border-b border-border">
              <SortableTh column="name" label="Agent Name" />
              <SortableTh column="mode" label="Mode" />
              <SortableTh column="status" label="Status" />
              <SortableTh column="initiative" label="Initiative" />
              <SortableTh column="task" label="Task" />
              <SortableTh column="started" label="Started" />
              <SortableTh column="questions" label="Questions" className="text-right" />
              <SortableTh column="messages" label="Messages" className="text-right" />
              <SortableTh column="subagents" label="Subagents" className="text-right" />
              <SortableTh column="compactions" label="Compactions" className="text-right" />
            </tr>
          </thead>
          <tbody>
            {isLoading
              ? Array.from({ length: 5 }).map((_, i) => (
                  <tr key={i}>
                    <td colSpan={10} className="px-3 py-2">
                      <div className="h-4 bg-muted rounded animate-pulse" />
                    </td>
                  </tr>
                ))
              : sortedAgents.map((agent) => (
                  <tr key={agent.id} className="border-b border-border/50 hover:bg-muted/30">
                    <td className="px-3 py-2">
                      <Link to="/agents" search={{ selected: agent.id }}>
                        {agent.name}
                      </Link>
                    </td>
                    <td className="px-3 py-2">{agent.mode}</td>
                    <td className="px-3 py-2">{agent.status}</td>
                    <td className="px-3 py-2">{agent.initiativeName ?? '—'}</td>
                    <td className="px-3 py-2">{agent.taskName ?? '—'}</td>
                    <td className="px-3 py-2">
                      {new Date(agent.createdAt).toLocaleString()}
                    </td>
                    <td
                      data-testid={`cell-questions-${agent.id}`}
                      className={agent.questionsCount > 0 ? 'cursor-pointer hover:bg-muted/50 text-right px-3 py-2' : 'text-muted-foreground text-right px-3 py-2'}
                      onClick={agent.questionsCount > 0
                        ? () => setDrilldown({ type: 'questions', agentId: agent.id, agentName: agent.name })
                        : undefined}
                    >
                      {agent.questionsCount}
                    </td>
                    <td
                      data-testid={`cell-messages-${agent.id}`}
                      className={agent.messagesCount > 0 ? 'cursor-pointer hover:bg-muted/50 text-right px-3 py-2' : 'text-muted-foreground text-right px-3 py-2'}
                      onClick={agent.messagesCount > 0
                        ? () => setDrilldown({ type: 'messages', agentId: agent.id, agentName: agent.name })
                        : undefined}
                    >
                      {agent.messagesCount}
                    </td>
                    <td
                      data-testid={`cell-subagents-${agent.id}`}
                      className={agent.subagentsCount > 0 ? 'cursor-pointer hover:bg-muted/50 text-right px-3 py-2' : 'text-muted-foreground text-right px-3 py-2'}
                      onClick={agent.subagentsCount > 0
                        ? () => setDrilldown({ type: 'subagents', agentId: agent.id, agentName: agent.name })
                        : undefined}
                    >
                      {agent.subagentsCount}
                    </td>
                    <td
                      data-testid={`cell-compactions-${agent.id}`}
                      className={agent.compactionsCount > 0 ? 'cursor-pointer hover:bg-muted/50 text-right px-3 py-2' : 'text-muted-foreground text-right px-3 py-2'}
                      onClick={agent.compactionsCount > 0
                        ? () => setDrilldown({ type: 'compactions', agentId: agent.id, agentName: agent.name })
                        : undefined}
                    >
                      {agent.compactionsCount}
                    </td>
                  </tr>
                ))}
          </tbody>
        </table>
      )}

      <CompactionEventsDialog
        open={drilldown?.type === 'compactions'}
        onOpenChange={(open) => { if (!open) setDrilldown(null) }}
        agentId={drilldown?.agentId ?? ''}
        agentName={drilldown?.agentName ?? ''}
        isAgentRunning={isAgentRunning}
      />
      <SubagentSpawnsDialog
        open={drilldown?.type === 'subagents'}
        onOpenChange={(open) => { if (!open) setDrilldown(null) }}
        agentId={drilldown?.agentId ?? ''}
        agentName={drilldown?.agentName ?? ''}
        isAgentRunning={isAgentRunning}
      />
      <QuestionsAskedDialog
        open={drilldown?.type === 'questions'}
        onOpenChange={(open) => { if (!open) setDrilldown(null) }}
        agentId={drilldown?.agentId ?? ''}
        agentName={drilldown?.agentName ?? ''}
        isAgentRunning={isAgentRunning}
      />
      <InterAgentMessagesDialog
        open={drilldown?.type === 'messages'}
        onOpenChange={(open) => { if (!open) setDrilldown(null) }}
        agentId={drilldown?.agentId ?? ''}
        agentName={drilldown?.agentName ?? ''}
        isAgentRunning={isAgentRunning}
      />
    </div>
  )
}
