import { useMemo, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import { useRun, useUpdateRun, useNamingCategories } from '../hooks/useRuns'
import { useGameRoutes } from '../hooks/useGames'
import { useCreateEncounter, useUpdateEncounter } from '../hooks/useEncounters'
import {
  CustomRulesDisplay,
  StatCard,
  PokemonCard,
  RuleBadges,
  StatusChangeModal,
  EndRunModal,
} from '../components'
import type { RunStatus, EncounterDetail, RunVisibility } from '../types'

type TeamSortKey = 'route' | 'level' | 'species' | 'dex'

function sortEncounters(encounters: EncounterDetail[], key: TeamSortKey): EncounterDetail[] {
  return [...encounters].sort((a, b) => {
    switch (key) {
      case 'route':
        return a.route.order - b.route.order
      case 'level':
        return (a.catchLevel ?? 0) - (b.catchLevel ?? 0)
      case 'species': {
        const nameA = (a.currentPokemon ?? a.pokemon).name
        const nameB = (b.currentPokemon ?? b.pokemon).name
        return nameA.localeCompare(nameB)
      }
      case 'dex':
        return (
          (a.currentPokemon ?? a.pokemon).nationalDex - (b.currentPokemon ?? b.pokemon).nationalDex
        )
      default:
        return 0
    }
  })
}

const statusStyles: Record<RunStatus, string> = {
  active: 'bg-green-900/40 text-green-300 light:bg-green-100 light:text-green-800',
  completed: 'bg-blue-900/40 text-blue-300 light:bg-blue-100 light:text-blue-800',
  failed: 'bg-red-900/40 text-red-300 light:bg-red-100 light:text-red-800',
}

function formatDuration(start: string, end: string) {
  const ms = new Date(end).getTime() - new Date(start).getTime()
  const days = Math.floor(ms / (1000 * 60 * 60 * 24))
  if (days === 0) return 'Less than a day'
  if (days === 1) return '1 day'
  return `${days} days`
}

export function RunDashboard() {
  const { runId } = useParams<{ runId: string }>()
  const runIdNum = Number(runId)
  const { data: run, isLoading, error } = useRun(runIdNum)
  const { data: routes } = useGameRoutes(run?.gameId ?? null)
  const { user } = useAuth()
  const createEncounter = useCreateEncounter(runIdNum)
  const updateEncounter = useUpdateEncounter(runIdNum)
  const updateRun = useUpdateRun(runIdNum)
  const { data: namingCategories } = useNamingCategories()
  const [selectedEncounter, setSelectedEncounter] = useState<EncounterDetail | null>(null)
  const [showEndRun, setShowEndRun] = useState(false)
  const [teamSort, setTeamSort] = useState<TeamSortKey>('route')

  const isOwner = user && run?.owner?.id === user.id
  const canEdit = isOwner

  const encounters = run?.encounters ?? []
  const alive = useMemo(
    () =>
      sortEncounters(
        encounters.filter((e) => e.status === 'caught' && e.faintLevel === null),
        teamSort
      ),
    [encounters, teamSort]
  )
  const dead = useMemo(
    () =>
      sortEncounters(
        encounters.filter((e) => e.status === 'caught' && e.faintLevel !== null),
        teamSort
      ),
    [encounters, teamSort]
  )

  if (isLoading) {
    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-status-failed-bg p-4 text-status-failed">
          Failed to load run. It may not exist.
        </div>
        <Link to="/runs" className="inline-block mt-4 text-blue-600 hover:underline">
          Back to runs
        </Link>
      </div>
    )
  }

  const isActive = run.status === 'active'
  const visitedRoutes = new Set(run.encounters.map((e) => e.routeId)).size
  const totalRoutes = routes?.length

  return (
    <div className="max-w-4xl mx-auto p-8">
      {/* Header */}
      <div className="mb-6">
        <Link
          to="/runs"
          className="text-sm text-text-tertiary hover:text-text-primary mb-2 inline-block"
        >
          &larr; All Runs
        </Link>
        <div className="flex items-start justify-between">
          <div>
            <h1 className="text-3xl font-bold text-text-primary">{run.name}</h1>
            <p className="text-text-tertiary mt-1">
              {run.game.name} &middot;{' '}
              {run.game.region.charAt(0).toUpperCase() + run.game.region.slice(1)} &middot; Started{' '}
              {new Date(run.startedAt).toLocaleDateString(undefined, {
                year: 'numeric',
                month: 'short',
                day: 'numeric',
              })}
            </p>
          </div>
          <span
            className={`px-3 py-1 rounded-full text-sm font-medium capitalize ${statusStyles[run.status]}`}
          >
            {run.status}
          </span>
        </div>
      </div>

      {/* Read-only Banner */}
      {!canEdit && run.owner && (
        <div className="rounded-lg p-3 mb-6 bg-surface-2 border border-border-default">
          <div className="flex items-center gap-2 text-text-secondary">
            <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
              />
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
              />
            </svg>
            <span className="text-sm">
              Viewing {run.owner.displayName ? `${run.owner.displayName}'s` : "another player's"}{' '}
              run (read-only)
            </span>
          </div>
        </div>
      )}

      {/* Completion Banner */}
      {!isActive && (
        <div
          className={`rounded-lg p-4 mb-6 ${
            run.status === 'completed'
              ? 'bg-blue-900/20 border border-blue-800'
              : 'bg-status-failed-bg border border-red-800'
          }`}
        >
          <div className="flex items-center gap-3">
            <span className="text-2xl">
              {run.status === 'completed' ? '\u{1f3c6}' : '\u{1faa6}'}
            </span>
            <div>
              <p
                className={`font-semibold ${
                  run.status === 'completed' ? 'text-blue-200' : 'text-red-200'
                }`}
              >
                {run.status === 'completed' ? 'Victory!' : 'Defeat'}
              </p>
              <p
                className={`text-sm ${
                  run.status === 'completed' ? 'text-text-link' : 'text-status-failed'
                }`}
              >
                {run.completedAt && (
                  <>
                    Ended{' '}
                    {new Date(run.completedAt).toLocaleDateString(undefined, {
                      year: 'numeric',
                      month: 'short',
                      day: 'numeric',
                    })}
                    {' \u00b7 '}
                    Duration: {formatDuration(run.startedAt, run.completedAt)}
                  </>
                )}
              </p>
            </div>
          </div>
        </div>
      )}

      {/* Stats */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
        <StatCard label="Encounters" value={run.encounters.length} color="blue" />
        <StatCard label="Alive" value={alive.length} color="green" />
        <StatCard label="Deaths" value={dead.length} color="red" />
        <StatCard label="Routes Visited" value={visitedRoutes} total={totalRoutes} color="purple" />
      </div>

      {/* Rules */}
      <div className="mb-6">
        <h2 className="text-sm font-medium text-text-tertiary mb-2">Active Rules</h2>
        <RuleBadges rules={run.rules} />
        <CustomRulesDisplay customRules={run.rules?.customRules ?? ''} />
      </div>

      {/* Visibility */}
      {canEdit && (
        <div className="mb-6">
          <h2 className="text-sm font-medium text-text-tertiary mb-2">Visibility</h2>
          <select
            value={run.visibility}
            onChange={(e) => updateRun.mutate({ visibility: e.target.value as RunVisibility })}
            className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
          >
            <option value="public">Public</option>
            <option value="private">Private</option>
          </select>
          <p className="mt-1 text-xs text-text-tertiary">
            {run.visibility === 'private'
              ? 'Only you can see this run'
              : 'Anyone can view this run'}
          </p>
        </div>
      )}

      {/* Naming Scheme */}
      {namingCategories && namingCategories.length > 0 && (
        <div className="mb-6">
          <h2 className="text-sm font-medium text-text-tertiary mb-2">Naming Scheme</h2>
          {isActive && canEdit ? (
            <select
              value={run.namingScheme ?? ''}
              onChange={(e) => updateRun.mutate({ namingScheme: e.target.value || null })}
              className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
            >
              <option value="">None</option>
              {namingCategories.map((cat) => (
                <option key={cat} value={cat}>
                  {cat.charAt(0).toUpperCase() + cat.slice(1)}
                </option>
              ))}
            </select>
          ) : (
            <span className="text-sm text-text-primary">
              {run.namingScheme
                ? run.namingScheme.charAt(0).toUpperCase() + run.namingScheme.slice(1)
                : 'None'}
            </span>
          )}
        </div>
      )}

      {/* Active Team */}
      <div className="mb-6">
        <div className="flex items-center justify-between mb-3">
          <h2 className="text-lg font-semibold text-text-primary">
            {isActive ? 'Active Team' : 'Final Team'}
          </h2>
          {alive.length > 1 && (
            <select
              value={teamSort}
              onChange={(e) => setTeamSort(e.target.value as TeamSortKey)}
              className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
            >
              <option value="route">Route Order</option>
              <option value="level">Catch Level</option>
              <option value="species">Species Name</option>
              <option value="dex">National Dex</option>
            </select>
          )}
        </div>
        {alive.length === 0 ? (
          <p className="text-text-tertiary text-sm">
            No pokemon caught yet — head to encounters to start building your team!
          </p>
        ) : (
          <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3">
            {alive.map((enc) => (
              <PokemonCard
                key={enc.id}
                encounter={enc}
                onClick={isActive && canEdit ? () => setSelectedEncounter(enc) : undefined}
              />
            ))}
          </div>
        )}
      </div>

      {/* Graveyard */}
      {dead.length > 0 && (
        <div className="mb-6">
          <h2 className="text-lg font-semibold text-text-primary mb-3">Graveyard</h2>
          <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3">
            {dead.map((enc) => (
              <PokemonCard
                key={enc.id}
                encounter={enc}
                showFaintLevel
                onClick={isActive && canEdit ? () => setSelectedEncounter(enc) : undefined}
              />
            ))}
          </div>
        </div>
      )}

      {/* Quick Actions */}
      <div className="mt-8 flex gap-3">
        {isActive && canEdit && (
          <>
            <Link
              to={`/runs/${runId}/encounters`}
              className="px-4 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-accent-400 focus:ring-offset-2 transition-colors"
            >
              Log Encounter
            </Link>
            <button
              onClick={() => setShowEndRun(true)}
              className="px-4 py-2 border border-border-default rounded-lg font-medium hover:bg-surface-2 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
            >
              End Run
            </button>
          </>
        )}
      </div>

      {/* Status Change Modal */}
      {selectedEncounter && (
        <StatusChangeModal
          encounter={selectedEncounter}
          onUpdate={(data) => {
            updateEncounter.mutate(data, {
              onSuccess: () => setSelectedEncounter(null),
            })
          }}
          onClose={() => setSelectedEncounter(null)}
          isPending={updateEncounter.isPending}
          region={run?.game.region}
          onCreateEncounter={(data) => {
            createEncounter.mutate(data)
          }}
        />
      )}

      {/* End Run Modal */}
      {showEndRun && (
        <EndRunModal
          onConfirm={(status) => {
            updateRun.mutate({ status }, { onSuccess: () => setShowEndRun(false) })
          }}
          onClose={() => setShowEndRun(false)}
          isPending={updateRun.isPending}
        />
      )}
    </div>
  )
}
