import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { RulesConfiguration, StepIndicator } from '../components'
import { useRegions, useCreateGenlocke } from '../hooks/useGenlockes'
import type { Game, GenlockeRules, Region } from '../types'
import { DEFAULT_RULES } from '../types'
import type { NuzlockeRules } from '../types/rules'
import { RULE_DEFINITIONS } from '../types/rules'

const STEPS = ['Name', 'Select Games', 'Rules', 'Confirm']
const DEFAULT_COLOR = '#6366f1'

interface LegEntry {
  region: string
  game: Game
}

type PresetType = 'true' | 'normal' | 'custom' | null

function buildLegsFromPreset(
  regions: Region[],
  preset: 'true' | 'normal',
): LegEntry[] {
  const legs: LegEntry[] = []
  for (const region of regions) {
    const targetSlug =
      preset === 'true'
        ? region.genlockeDefaults.trueGenlocke
        : region.genlockeDefaults.normalGenlocke
    const game = region.games.find((g) => g.slug === targetSlug)
    if (game) {
      legs.push({ region: region.name, game })
    }
  }
  return legs
}

export function NewGenlocke() {
  const navigate = useNavigate()
  const { data: regions, isLoading: regionsLoading } = useRegions()
  const createGenlocke = useCreateGenlocke()

  const [step, setStep] = useState(1)
  const [name, setName] = useState('')
  const [legs, setLegs] = useState<LegEntry[]>([])
  const [preset, setPreset] = useState<PresetType>(null)
  const [nuzlockeRules, setNuzlockeRules] = useState<NuzlockeRules>(DEFAULT_RULES)
  const [genlockeRules, setGenlockeRules] = useState<GenlockeRules>({ retireHoF: false })

  const handlePresetSelect = (type: PresetType) => {
    setPreset(type)
    if (!regions) return
    if (type === 'true' || type === 'normal') {
      setLegs(buildLegsFromPreset(regions, type))
    } else if (type === 'custom') {
      setLegs([])
    }
  }

  const handleGameChange = (index: number, game: Game) => {
    setLegs((prev) => prev.map((leg, i) => (i === index ? { ...leg, game } : leg)))
  }

  const handleRemoveLeg = (index: number) => {
    setLegs((prev) => prev.filter((_, i) => i !== index))
  }

  const handleAddLeg = (region: Region) => {
    const defaultSlug = region.genlockeDefaults.normalGenlocke
    const game = region.games.find((g) => g.slug === defaultSlug) ?? region.games[0]
    if (game) {
      setLegs((prev) => [...prev, { region: region.name, game }])
    }
  }

  const handleMoveLeg = (index: number, direction: 'up' | 'down') => {
    const target = direction === 'up' ? index - 1 : index + 1
    if (target < 0 || target >= legs.length) return
    setLegs((prev) => {
      const next = [...prev]
      ;[next[index], next[target]] = [next[target], next[index]]
      return next
    })
  }

  const handleCreate = () => {
    if (!name.trim() || legs.length === 0) return
    createGenlocke.mutate(
      {
        name: name.trim(),
        gameIds: legs.map((l) => l.game.id),
        genlockeRules,
        nuzlockeRules,
      },
      {
        onSuccess: (data) => {
          const firstLeg = data.legs.find((l) => l.legOrder === 1)
          if (firstLeg?.runId) {
            navigate(`/runs/${firstLeg.runId}`)
          } else {
            navigate('/runs')
          }
        },
      },
    )
  }

  const enabledRuleCount = RULE_DEFINITIONS.filter((r) => nuzlockeRules[r.key]).length
  const totalRuleCount = RULE_DEFINITIONS.length

  // Regions not yet used in legs (for "add leg" picker)
  const availableRegions = regions?.filter(
    (r) => !legs.some((l) => l.region === r.name),
  ) ?? []

  return (
    <div className="max-w-4xl mx-auto p-8">
      <h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100 mb-2">
        New Genlocke
      </h1>
      <p className="text-gray-600 dark:text-gray-400 mb-6">
        Set up your generational challenge.
      </p>

      <StepIndicator currentStep={step} onStepClick={setStep} steps={STEPS} />

      {/* Step 1: Name */}
      {step === 1 && (
        <div>
          <h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-4">
            Name Your Genlocke
          </h2>
          <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
            <label
              htmlFor="genlocke-name"
              className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
            >
              Genlocke Name
            </label>
            <input
              id="genlocke-name"
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              className="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
              placeholder="My Genlocke"
              maxLength={100}
              autoFocus
            />
          </div>

          <div className="mt-6 flex justify-end">
            <button
              type="button"
              disabled={!name.trim()}
              onClick={() => setStep(2)}
              className="px-6 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              Next
            </button>
          </div>
        </div>
      )}

      {/* Step 2: Game Selection */}
      {step === 2 && (
        <div>
          <h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-4">
            Select Games
          </h2>

          {/* Preset buttons */}
          <div className="flex gap-3 mb-6">
            {(['true', 'normal', 'custom'] as const).map((type) => {
              const labels = {
                true: 'True Genlocke',
                normal: 'Normal Genlocke',
                custom: 'Custom',
              }
              const descriptions = {
                true: 'Original releases only',
                normal: 'Latest version per region',
                custom: 'Build your own',
              }
              const isActive = preset === type
              return (
                <button
                  key={type}
                  type="button"
                  onClick={() => handlePresetSelect(type)}
                  className={`flex-1 p-4 rounded-lg border-2 text-left transition-colors ${
                    isActive
                      ? 'border-blue-600 bg-blue-50 dark:bg-blue-900/20'
                      : 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
                  }`}
                >
                  <div className={`font-medium ${isActive ? 'text-blue-600 dark:text-blue-400' : 'text-gray-900 dark:text-gray-100'}`}>
                    {labels[type]}
                  </div>
                  <div className="text-sm text-gray-500 dark:text-gray-400 mt-1">
                    {descriptions[type]}
                  </div>
                </button>
              )
            })}
          </div>

          {regionsLoading && (
            <div className="flex items-center justify-center py-12">
              <div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin" />
            </div>
          )}

          {/* Legs list */}
          {legs.length > 0 && (
            <div className="bg-white dark:bg-gray-800 rounded-lg shadow divide-y divide-gray-200 dark:divide-gray-700">
              {legs.map((leg, index) => (
                <LegRow
                  key={`${leg.region}-${index}`}
                  leg={leg}
                  index={index}
                  total={legs.length}
                  regions={regions ?? []}
                  onGameChange={(game) => handleGameChange(index, game)}
                  onRemove={() => handleRemoveLeg(index)}
                  onMove={(dir) => handleMoveLeg(index, dir)}
                />
              ))}
            </div>
          )}

          {/* Add leg button */}
          {preset === 'custom' && availableRegions.length > 0 && (
            <div className="mt-4">
              <AddLegDropdown regions={availableRegions} onAdd={handleAddLeg} />
            </div>
          )}

          {/* Also allow adding extra regions for presets */}
          {preset && preset !== 'custom' && availableRegions.length > 0 && legs.length > 0 && (
            <div className="mt-4">
              <AddLegDropdown regions={availableRegions} onAdd={handleAddLeg} />
            </div>
          )}

          <div className="mt-6 flex justify-between">
            <button
              type="button"
              onClick={() => setStep(1)}
              className="px-6 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg font-medium hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
            >
              Back
            </button>
            <button
              type="button"
              disabled={legs.length === 0}
              onClick={() => setStep(3)}
              className="px-6 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              Next
            </button>
          </div>
        </div>
      )}

      {/* Step 3: Rules */}
      {step === 3 && (
        <div>
          <RulesConfiguration rules={nuzlockeRules} onChange={setNuzlockeRules} />

          {/* Genlocke-specific rules */}
          <div className="mt-6 bg-white dark:bg-gray-800 rounded-lg shadow">
            <div className="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
              <h3 className="text-lg font-medium text-gray-900 dark:text-gray-100">
                Genlocke Rules
              </h3>
              <p className="text-sm text-gray-500 dark:text-gray-400">
                Rules specific to the generational challenge
              </p>
            </div>
            <div className="px-4 py-4">
              <fieldset>
                <legend className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
                  Hall of Fame Pokemon
                </legend>
                <div className="space-y-3">
                  <label className="flex items-start gap-3 cursor-pointer">
                    <input
                      type="radio"
                      name="hofRule"
                      checked={!genlockeRules.retireHoF}
                      onChange={() => setGenlockeRules({ retireHoF: false })}
                      className="mt-0.5 w-4 h-4 text-blue-600 focus:ring-blue-500"
                    />
                    <div>
                      <div className="font-medium text-gray-900 dark:text-gray-100">
                        Keep Hall of Fame
                      </div>
                      <div className="text-sm text-gray-500 dark:text-gray-400">
                        Pokemon that beat the Elite Four can continue to the next leg
                      </div>
                    </div>
                  </label>
                  <label className="flex items-start gap-3 cursor-pointer">
                    <input
                      type="radio"
                      name="hofRule"
                      checked={genlockeRules.retireHoF}
                      onChange={() => setGenlockeRules({ retireHoF: true })}
                      className="mt-0.5 w-4 h-4 text-blue-600 focus:ring-blue-500"
                    />
                    <div>
                      <div className="font-medium text-gray-900 dark:text-gray-100">
                        Retire Hall of Fame
                      </div>
                      <div className="text-sm text-gray-500 dark:text-gray-400">
                        Pokemon that beat the Elite Four are retired and cannot be used in the next leg
                      </div>
                    </div>
                  </label>
                </div>
              </fieldset>
            </div>
          </div>

          <div className="mt-6 flex justify-between">
            <button
              type="button"
              onClick={() => setStep(2)}
              className="px-6 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg font-medium hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
            >
              Back
            </button>
            <button
              type="button"
              onClick={() => setStep(4)}
              className="px-6 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"
            >
              Next
            </button>
          </div>
        </div>
      )}

      {/* Step 4: Confirm */}
      {step === 4 && (
        <div>
          <h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-4">
            Confirm & Start
          </h2>

          <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6 space-y-4">
            <div>
              <h3 className="text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">
                Name
              </h3>
              <p className="text-gray-900 dark:text-gray-100 font-medium">{name}</p>
            </div>

            <div className="border-t border-gray-200 dark:border-gray-700 pt-4">
              <h3 className="text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">
                Legs ({legs.length})
              </h3>
              <ol className="space-y-2">
                {legs.map((leg, i) => (
                  <li key={i} className="flex items-center gap-3">
                    <span className="text-sm text-gray-400 dark:text-gray-500 w-6 text-right font-mono">
                      {i + 1}.
                    </span>
                    <GameThumb game={leg.game} />
                    <div>
                      <span className="text-gray-900 dark:text-gray-100 font-medium">
                        {leg.game.name}
                      </span>
                      <span className="text-sm text-gray-500 dark:text-gray-400 ml-2">
                        {leg.region.charAt(0).toUpperCase() + leg.region.slice(1)}
                      </span>
                    </div>
                  </li>
                ))}
              </ol>
            </div>

            <div className="border-t border-gray-200 dark:border-gray-700 pt-4">
              <h3 className="text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">
                Rules
              </h3>
              <dl className="space-y-1 text-sm">
                <div className="flex justify-between">
                  <dt className="text-gray-600 dark:text-gray-400">Nuzlocke Rules</dt>
                  <dd className="text-gray-900 dark:text-gray-100 font-medium">
                    {enabledRuleCount} of {totalRuleCount} enabled
                  </dd>
                </div>
                <div className="flex justify-between">
                  <dt className="text-gray-600 dark:text-gray-400">Hall of Fame</dt>
                  <dd className="text-gray-900 dark:text-gray-100 font-medium">
                    {genlockeRules.retireHoF ? 'Retire' : 'Keep'}
                  </dd>
                </div>
              </dl>
            </div>
          </div>

          {createGenlocke.error && (
            <div className="mt-4 rounded-lg bg-red-50 dark:bg-red-900/20 p-4 text-red-700 dark:text-red-400">
              Failed to create genlocke. Please try again.
            </div>
          )}

          <div className="mt-6 flex justify-between">
            <button
              type="button"
              onClick={() => setStep(3)}
              className="px-6 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg font-medium hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 transition-colors"
            >
              Back
            </button>
            <button
              type="button"
              disabled={createGenlocke.isPending}
              onClick={handleCreate}
              className="px-6 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              {createGenlocke.isPending ? 'Creating...' : 'Start Genlocke'}
            </button>
          </div>
        </div>
      )}
    </div>
  )
}

// --- Sub-components ---

function LegRow({
  leg,
  index,
  total,
  regions,
  onGameChange,
  onRemove,
  onMove,
}: {
  leg: LegEntry
  index: number
  total: number
  regions: Region[]
  onGameChange: (game: Game) => void
  onRemove: () => void
  onMove: (dir: 'up' | 'down') => void
}) {
  const region = regions.find((r) => r.name === leg.region)
  const games = region?.games ?? []

  return (
    <div className="flex items-center gap-3 px-4 py-3">
      <span className="text-sm text-gray-400 dark:text-gray-500 w-6 text-right font-mono shrink-0">
        {index + 1}.
      </span>
      <GameThumb game={leg.game} />
      <div className="flex-1 min-w-0">
        <div className="text-sm text-gray-500 dark:text-gray-400">
          {leg.region.charAt(0).toUpperCase() + leg.region.slice(1)}
        </div>
        {games.length > 1 ? (
          <select
            value={leg.game.id}
            onChange={(e) => {
              const game = games.find((g) => g.id === Number(e.target.value))
              if (game) onGameChange(game)
            }}
            className="mt-1 w-full max-w-xs px-2 py-1 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            {games.map((g) => (
              <option key={g.id} value={g.id}>
                {g.name}
              </option>
            ))}
          </select>
        ) : (
          <div className="text-gray-900 dark:text-gray-100 font-medium">
            {leg.game.name}
          </div>
        )}
      </div>
      <div className="flex items-center gap-1 shrink-0">
        <button
          type="button"
          disabled={index === 0}
          onClick={() => onMove('up')}
          className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-30 disabled:cursor-not-allowed"
          title="Move up"
        >
          <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M5 15l7-7 7 7" />
          </svg>
        </button>
        <button
          type="button"
          disabled={index === total - 1}
          onClick={() => onMove('down')}
          className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-30 disabled:cursor-not-allowed"
          title="Move down"
        >
          <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
          </svg>
        </button>
        <button
          type="button"
          onClick={onRemove}
          className="p-1 text-red-400 hover:text-red-600 dark:hover:text-red-300"
          title="Remove leg"
        >
          <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>
    </div>
  )
}

function AddLegDropdown({
  regions,
  onAdd,
}: {
  regions: Region[]
  onAdd: (region: Region) => void
}) {
  const [open, setOpen] = useState(false)

  if (!open) {
    return (
      <button
        type="button"
        onClick={() => setOpen(true)}
        className="flex items-center gap-2 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium"
      >
        <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M12 4v16m8-8H4" />
        </svg>
        Add Region
      </button>
    )
  }

  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-3">
      <div className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
        Select a region to add
      </div>
      <div className="flex flex-wrap gap-2">
        {regions.map((region) => (
          <button
            key={region.name}
            type="button"
            onClick={() => {
              onAdd(region)
              setOpen(false)
            }}
            className="px-3 py-1.5 rounded-md text-sm bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
          >
            {region.name.charAt(0).toUpperCase() + region.name.slice(1)}
          </button>
        ))}
        <button
          type="button"
          onClick={() => setOpen(false)}
          className="px-3 py-1.5 rounded-md text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
        >
          Cancel
        </button>
      </div>
    </div>
  )
}

function GameThumb({ game }: { game: Game }) {
  const [imgIdx, setImgIdx] = useState(0)
  const backgroundColor = game.color ?? DEFAULT_COLOR
  const boxArtSrcs = [`/boxart/${game.slug}.png`, `/boxart/${game.slug}.jpg`]

  if (imgIdx >= boxArtSrcs.length) {
    return (
      <div
        className="w-10 h-10 rounded flex items-center justify-center flex-shrink-0"
        style={{ backgroundColor }}
      >
        <span className="text-white text-xs font-bold drop-shadow-md">
          {game.name.replace('Pokemon ', '').slice(0, 3)}
        </span>
      </div>
    )
  }

  return (
    <img
      src={boxArtSrcs[imgIdx]}
      alt={game.name}
      className="w-10 h-10 rounded object-cover flex-shrink-0"
      onError={() => setImgIdx((i) => i + 1)}
    />
  )
}
