import { useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { useRun } from '../hooks/useRuns'
import { useGameRoutes } from '../hooks/useGames'
import { useCreateEncounter, useUpdateEncounter } from '../hooks/useEncounters'
import { EncounterModal } from '../components'
import type { Route, EncounterDetail, EncounterStatus } from '../types'

type RouteStatus = 'caught' | 'fainted' | 'missed' | 'none'

function getRouteStatus(encounter?: EncounterDetail): RouteStatus {
  if (!encounter) return 'none'
  return encounter.status
}

const statusIndicator: Record<
  RouteStatus,
  { dot: string; label: string; bg: string }
> = {
  caught: {
    dot: 'bg-green-500',
    label: 'Caught',
    bg: 'bg-green-50 dark:bg-green-900/10',
  },
  fainted: {
    dot: 'bg-red-500',
    label: 'Fainted',
    bg: 'bg-red-50 dark:bg-red-900/10',
  },
  missed: {
    dot: 'bg-gray-400',
    label: 'Missed',
    bg: 'bg-gray-50 dark:bg-gray-900/10',
  },
  none: { dot: 'bg-gray-300 dark:bg-gray-600', label: '', bg: '' },
}

export function RunEncounters() {
  const { runId } = useParams<{ runId: string }>()
  const runIdNum = Number(runId)
  const { data: run, isLoading, error } = useRun(runIdNum)
  const { data: routes, isLoading: loadingRoutes } = useGameRoutes(
    run?.gameId ?? null,
  )
  const createEncounter = useCreateEncounter(runIdNum)
  const updateEncounter = useUpdateEncounter(runIdNum)

  const [selectedRoute, setSelectedRoute] = useState<Route | null>(null)
  const [editingEncounter, setEditingEncounter] =
    useState<EncounterDetail | null>(null)
  const [filter, setFilter] = useState<'all' | RouteStatus>('all')

  if (isLoading || loadingRoutes) {
    return (
      <div className="flex items-center justify-center py-16">
        <div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin" />
      </div>
    )
  }

  if (error || !run) {
    return (
      <div className="max-w-4xl mx-auto p-8">
        <div className="rounded-lg bg-red-50 dark:bg-red-900/20 p-4 text-red-700 dark:text-red-400">
          Failed to load run.
        </div>
        <Link
          to="/runs"
          className="inline-block mt-4 text-blue-600 hover:underline"
        >
          Back to runs
        </Link>
      </div>
    )
  }

  // Map routeId → encounter for quick lookup
  const encounterByRoute = new Map<number, EncounterDetail>()
  for (const enc of run.encounters) {
    encounterByRoute.set(enc.routeId, enc)
  }

  const allRoutes = routes ?? []
  const completedCount = allRoutes.filter((r) =>
    encounterByRoute.has(r.id),
  ).length

  // Filter routes
  const filteredRoutes =
    filter === 'all'
      ? allRoutes
      : allRoutes.filter((r) => {
          const enc = encounterByRoute.get(r.id)
          return getRouteStatus(enc) === filter
        })

  const handleRouteClick = (route: Route) => {
    const existing = encounterByRoute.get(route.id)
    if (existing) {
      setEditingEncounter(existing)
    } else {
      setEditingEncounter(null)
    }
    setSelectedRoute(route)
  }

  const handleCreate = (data: {
    routeId: number
    pokemonId: number
    nickname?: string
    status: EncounterStatus
    catchLevel?: number
  }) => {
    createEncounter.mutate(data, {
      onSuccess: () => {
        setSelectedRoute(null)
        setEditingEncounter(null)
      },
    })
  }

  const handleUpdate = (data: {
    id: number
    data: { nickname?: string; status?: EncounterStatus; faintLevel?: number }
  }) => {
    updateEncounter.mutate(data, {
      onSuccess: () => {
        setSelectedRoute(null)
        setEditingEncounter(null)
      },
    })
  }

  return (
    <div className="max-w-4xl mx-auto p-8">
      {/* Header */}
      <div className="mb-6">
        <Link
          to={`/runs/${runId}`}
          className="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 mb-2 inline-block"
        >
          &larr; {run.name}
        </Link>
        <h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">
          Encounters
        </h1>
        <p className="text-gray-600 dark:text-gray-400 mt-1">
          {run.game.name} &middot; {completedCount} / {allRoutes.length} routes
        </p>
      </div>

      {/* Progress bar */}
      <div className="mb-6">
        <div className="h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
          <div
            className="h-full bg-blue-500 rounded-full transition-all"
            style={{
              width: `${allRoutes.length > 0 ? (completedCount / allRoutes.length) * 100 : 0}%`,
            }}
          />
        </div>
      </div>

      {/* Filter tabs */}
      <div className="flex gap-2 mb-4 flex-wrap">
        {(
          [
            { key: 'all', label: 'All' },
            { key: 'none', label: 'Unvisited' },
            { key: 'caught', label: 'Caught' },
            { key: 'fainted', label: 'Fainted' },
            { key: 'missed', label: 'Missed' },
          ] as const
        ).map(({ key, label }) => (
          <button
            key={key}
            onClick={() => setFilter(key)}
            className={`px-3 py-1 rounded-full text-sm font-medium transition-colors ${
              filter === key
                ? 'bg-blue-600 text-white'
                : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
            }`}
          >
            {label}
          </button>
        ))}
      </div>

      {/* Route list */}
      <div className="space-y-1">
        {filteredRoutes.length === 0 && (
          <p className="text-gray-500 dark:text-gray-400 text-sm py-4 text-center">
            No routes match this filter
          </p>
        )}
        {filteredRoutes.map((route) => {
          const encounter = encounterByRoute.get(route.id)
          const rs = getRouteStatus(encounter)
          const si = statusIndicator[rs]

          return (
            <button
              key={route.id}
              type="button"
              onClick={() => handleRouteClick(route)}
              className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg text-left transition-colors hover:bg-gray-100 dark:hover:bg-gray-700/50 ${si.bg}`}
            >
              <span
                className={`w-2.5 h-2.5 rounded-full shrink-0 ${si.dot}`}
              />
              <div className="flex-1 min-w-0">
                <div className="text-sm font-medium text-gray-900 dark:text-gray-100">
                  {route.name}
                </div>
                {encounter && (
                  <div className="flex items-center gap-2 mt-0.5">
                    {encounter.pokemon.spriteUrl && (
                      <img
                        src={encounter.pokemon.spriteUrl}
                        alt={encounter.pokemon.name}
                        className="w-5 h-5"
                      />
                    )}
                    <span className="text-xs text-gray-500 dark:text-gray-400 capitalize">
                      {encounter.nickname ?? encounter.pokemon.name}
                      {encounter.status === 'caught' &&
                        encounter.faintLevel !== null &&
                        ' (dead)'}
                    </span>
                  </div>
                )}
              </div>
              <span className="text-xs text-gray-400 dark:text-gray-500 shrink-0">
                {si.label}
              </span>
            </button>
          )
        })}
      </div>

      {/* Encounter Modal */}
      {selectedRoute && (
        <EncounterModal
          route={selectedRoute}
          existing={editingEncounter ?? undefined}
          onSubmit={handleCreate}
          onUpdate={handleUpdate}
          onClose={() => {
            setSelectedRoute(null)
            setEditingEncounter(null)
          }}
          isPending={createEncounter.isPending || updateEncounter.isPending}
        />
      )}
    </div>
  )
}
