import { useEffect, useMemo, useRef, useState } from 'react'
import type { CharacterProfile, DungeonEncounter } from '../profile'
import { useDualScreen, useDualScreenWorkshopPublisher, type DualScreenWorkshopState } from '../dualScreen'
import { useGameAction, type InputAction } from '../input'

type HunterProfileScreenProps = {
  profile: CharacterProfile
  onBack: () => void
}

type BossEntry = {
  encounter: DungeonEncounter
  dungeonId: number
  dungeonName: string
  contentType: 'dungeon' | 'raid'
}

type CollectionItem = {
  key: string
  glyph: string
  name: string
  chance: string
  quantity: number
  rarity: 'stat' | 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'
  source: string
}

type HunterProfileTab = 'stats' | 'collection'

type HunterProfileNavEntry =
  | { kind: 'back'; key: string; row: number; column: number }
  | { kind: 'tab'; key: string; row: number; column: number; tab: HunterProfileTab }
  | { kind: 'stat'; key: string; row: number; column: number; index: number }
  | { kind: 'boss'; key: string; row: number; column: number; bossId: number }
  | { kind: 'item'; key: string; row: number; column: number; itemKey: string }

const HUNTER_PROFILE_DROP_COLUMNS = 6

function bossInitials(name: string) {
  return name
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map((part) => part[0]?.toUpperCase() ?? '')
    .join('')
}

function dropChanceLabel(chance: number) {
  if (chance <= 0) return 'Unavailable'
  const denominator = Math.round(1 / chance)
  if (denominator >= 10) return `1 in ${denominator}`
  return `${Math.round(chance * 100)}%`
}

function purplePetKey(encounterId: number) {
  return `purple:${encounterId}`
}

export function HunterProfileScreen({ profile, onBack }: HunterProfileScreenProps) {
  const [activeTab, setActiveTab] = useState<HunterProfileTab>('stats')
  const [selectedIndex, setSelectedIndex] = useState(1)
  const screenRef = useRef<HTMLElement | null>(null)
  const { enabled: dualScreenEnabled } = useDualScreen()
  const bosses = useMemo<BossEntry[]>(() => profile.dungeons.flatMap((dungeon) =>
    dungeon.encounters
      .filter((encounter) => encounter.isBoss)
      .map((encounter) => ({
        encounter,
        dungeonId: dungeon.id,
        dungeonName: dungeon.name,
        contentType: dungeon.contentType,
      })),
  ), [profile.dungeons])
  const [selectedBossId, setSelectedBossId] = useState(() => bosses[0]?.encounter.id ?? 0)
  const [focusedItemKey, setFocusedItemKey] = useState<string | null>(null)
  const selectedBoss = bosses.find((boss) => boss.encounter.id === selectedBossId) ?? bosses[0]
  const bossKills = useMemo(() => profile.hunterStats?.bossKills ?? {}, [profile.hunterStats?.bossKills])
  const bossPets = useMemo(() => profile.hunterStats?.bossPets ?? {}, [profile.hunterStats?.bossPets])
  const inventoryQuantities = useMemo(
    () => new Map(profile.inventory.map((item) => [item.id, item.quantity])),
    [profile.inventory],
  )
  const totalBossKills = bosses.reduce((total, boss) => total + (bossKills[String(boss.encounter.id)] ?? 0), 0)
  const mostKilledBoss = bosses.reduce<BossEntry | null>((best, boss) => {
    if (!best) return boss
    return (bossKills[String(boss.encounter.id)] ?? 0) > (bossKills[String(best.encounter.id)] ?? 0)
      ? boss
      : best
  }, null)
  const matchesPlayed = profile.hunterStats?.pvpMatchesPlayed ?? 0
  const matchesWon = profile.hunterStats?.pvpMatchesWon ?? 0
  const winRate = matchesPlayed > 0 ? Math.round((matchesWon / matchesPlayed) * 100) : 0
  const collectionItems = useMemo<CollectionItem[]>(() => {
    if (!selectedBoss) return []
    return [
      {
        key: `kills:${selectedBoss.encounter.id}`,
        glyph: 'K',
        name: 'Boss Kills',
        chance: 'Defeats',
        quantity: bossKills[String(selectedBoss.encounter.id)] ?? 0,
        rarity: 'stat',
        source: selectedBoss.encounter.enemyName,
      },
      ...selectedBoss.encounter.lootTables.map((drop) => ({
        key: `drop:${drop.difficultyId}:${drop.id}`,
        glyph: drop.glyph,
        name: drop.name,
        chance: dropChanceLabel(drop.dropChance),
        quantity: inventoryQuantities.get(drop.id) ?? 0,
        rarity: drop.rarity,
        source: selectedBoss.encounter.enemyName,
      })),
      {
        key: `pet:${selectedBoss.encounter.id}`,
        glyph: '*',
        name: `${selectedBoss.encounter.enemyName} Pet`,
        chance: '1 in 500',
        quantity: bossPets[String(selectedBoss.encounter.id)] ?? 0,
        rarity: 'legendary',
        source: selectedBoss.encounter.enemyName,
      },
      {
        key: `purple-pet:${selectedBoss.encounter.id}`,
        glyph: 'P',
        name: `Purple ${selectedBoss.encounter.enemyName} Pet`,
        chance: '1 in 500',
        quantity: bossPets[purplePetKey(selectedBoss.encounter.id)] ?? 0,
        rarity: 'epic',
        source: `${selectedBoss.encounter.enemyName} Roguelike`,
      },
    ]
  }, [bossKills, bossPets, inventoryQuantities, selectedBoss])
  const statTiles = useMemo(() => [
    {
      key: 'stat:total-kills',
      label: 'Total Boss Kills',
      value: totalBossKills,
    },
    {
      key: 'stat:most-killed',
      label: 'Most Killed Boss',
      value: totalBossKills > 0 && mostKilledBoss ? mostKilledBoss.encounter.enemyName : 'None',
      detail: totalBossKills > 0 && mostKilledBoss ? `${bossKills[String(mostKilledBoss.encounter.id)] ?? 0} kills` : '0 kills',
    },
    {
      key: 'stat:pvp-matches',
      label: 'PvP Matches',
      value: matchesPlayed,
    },
    {
      key: 'stat:pvp-wins',
      label: 'PvP Wins',
      value: matchesWon,
    },
    {
      key: 'stat:pvp-win-rate',
      label: 'PvP Win Rate',
      value: `${winRate}%`,
    },
  ], [bossKills, matchesPlayed, matchesWon, mostKilledBoss, totalBossKills, winRate])
  const focusedItem = collectionItems.find((item) => item.key === focusedItemKey) ?? collectionItems[0] ?? null
  const navEntries = useMemo<HunterProfileNavEntry[]>(() => {
    const entries: HunterProfileNavEntry[] = [
      { kind: 'back', key: 'back', row: 0, column: 0 },
      { kind: 'tab', key: 'tab:stats', row: 0, column: 1, tab: 'stats' },
      { kind: 'tab', key: 'tab:collection', row: 0, column: 2, tab: 'collection' },
    ]
    if (activeTab === 'stats') {
      entries.push(...statTiles.map((tile, index) => ({
        kind: 'stat' as const,
        key: tile.key,
        row: 1,
        column: index,
        index,
      })))
    } else {
      entries.push(
        ...bosses.map((boss, index) => ({
          kind: 'boss' as const,
          key: `boss:${boss.encounter.id}`,
          row: index + 1,
          column: 0,
          bossId: boss.encounter.id,
        })),
        ...collectionItems.map((item, index) => ({
          kind: 'item' as const,
          key: `item:${item.key}`,
          row: Math.floor(index / HUNTER_PROFILE_DROP_COLUMNS) + 1,
          column: (index % HUNTER_PROFILE_DROP_COLUMNS) + 1,
          itemKey: item.key,
        })),
      )
    }
    return entries
  }, [activeTab, bosses, collectionItems, statTiles])
  const activeIndex = Math.min(selectedIndex, Math.max(0, navEntries.length - 1))
  const activeEntry = navEntries[activeIndex]
  const itemDetailState = useMemo<DualScreenWorkshopState | null>(() => {
    if (activeTab !== 'collection' || !selectedBoss || !focusedItem) return null
    return {
      mode: 'collection',
      title: focusedItem.name,
      subtitle: selectedBoss.encounter.enemyName,
      summary: `Owned x${focusedItem.quantity}`,
      items: [
        {
          glyph: focusedItem.glyph,
          title: 'Drop Rate',
          meta: focusedItem.chance,
          detail: focusedItem.source,
          status: focusedItem.quantity > 0 ? 'Collected' : 'Missing',
        },
        {
          title: 'Boss Kills',
          meta: `${bossKills[String(selectedBoss.encounter.id)] ?? 0}`,
          detail: selectedBoss.dungeonName,
        },
      ],
    }
  }, [activeTab, bossKills, focusedItem, selectedBoss])
  useDualScreenWorkshopPublisher(itemDetailState, dualScreenEnabled)

  function selected(entryKey: string) {
    return activeEntry?.key === entryKey
  }

  function selectKey(entryKey: string) {
    const index = navEntries.findIndex((entry) => entry.key === entryKey)
    if (index >= 0) setSelectedIndex(index)
  }

  function selectTab(tab: HunterProfileTab) {
    setActiveTab(tab)
    setSelectedIndex(tab === 'stats' ? 1 : 2)
  }

  function selectBoss(bossId: number) {
    setSelectedBossId(bossId)
    setFocusedItemKey(null)
  }

  function moveSelection(action: InputAction) {
    if (!action.startsWith('navigate') || navEntries.length === 0) return
    setSelectedIndex((current) => {
      const bounded = Math.min(current, navEntries.length - 1)
      const active = navEntries[bounded]
      if (!active) return 0
      const candidates = navEntries
        .map((entry, index) => ({ entry, index }))
        .filter(({ index }) => index !== bounded)
        .filter(({ entry }) => {
          if (action === 'navigateLeft') return entry.column < active.column
          if (action === 'navigateRight') return entry.column > active.column
          if (action === 'navigateUp') return entry.row < active.row
          return entry.row > active.row
        })
      if (candidates.length === 0) return bounded
      candidates.sort((a, b) => {
        const aPrimary = Math.abs(a.entry.row - active.row) + Math.abs(a.entry.column - active.column)
        const bPrimary = Math.abs(b.entry.row - active.row) + Math.abs(b.entry.column - active.column)
        const aSecondary = action === 'navigateLeft' || action === 'navigateRight'
          ? Math.abs(a.entry.row - active.row)
          : Math.abs(a.entry.column - active.column)
        const bSecondary = action === 'navigateLeft' || action === 'navigateRight'
          ? Math.abs(b.entry.row - active.row)
          : Math.abs(b.entry.column - active.column)
        return aPrimary - bPrimary || aSecondary - bSecondary || a.index - b.index
      })
      return candidates[0]?.index ?? bounded
    })
  }

  function openEntry(entry: HunterProfileNavEntry | undefined) {
    if (!entry) return
    if (entry.kind === 'back') onBack()
    else if (entry.kind === 'tab') selectTab(entry.tab)
    else if (entry.kind === 'boss') selectBoss(entry.bossId)
    else if (entry.kind === 'item') setFocusedItemKey(entry.itemKey)
  }

  useEffect(() => {
    if (!activeEntry) return
    screenRef.current
      ?.querySelector<HTMLElement>('[data-game-selected="true"]')
      ?.scrollIntoView({ block: 'nearest', inline: 'nearest' })
  }, [activeEntry])

  useGameAction((action, inputDevice) => {
    if (inputDevice !== 'controller') return
    if (action === 'back') {
      onBack()
      return
    }
    if (action === 'confirm') {
      openEntry(activeEntry)
      return
    }
    moveSelection(action)
  })

  return (
    <section className="content-screen hunter-profile-screen" data-game-nav-active="true" ref={screenRef}>
      <div className="screen-heading hunter-profile-heading">
        <div className="equipment-tabs hunter-profile-tabs" role="tablist" aria-label="Hunter profile tabs">
          <button
            className={`equipment-tab ${activeTab === 'stats' ? 'active' : ''} ${selected('tab:stats') ? 'game-selected' : ''}`}
            data-controller-nav="skip"
            data-game-selected={selected('tab:stats') ? 'true' : undefined}
            onClick={() => selectTab('stats')}
            onPointerDown={() => selectKey('tab:stats')}
            type="button"
            role="tab"
            aria-selected={activeTab === 'stats'}
          >
            Stats
          </button>
          <button
            className={`equipment-tab ${activeTab === 'collection' ? 'active' : ''} ${selected('tab:collection') ? 'game-selected' : ''}`}
            data-controller-nav="skip"
            data-game-selected={selected('tab:collection') ? 'true' : undefined}
            onClick={() => selectTab('collection')}
            onPointerDown={() => selectKey('tab:collection')}
            type="button"
            role="tab"
            aria-selected={activeTab === 'collection'}
          >
            Collection Log
          </button>
        </div>
        <button
          className={`back-button ${selected('back') ? 'game-selected' : ''}`}
          data-controller-nav="skip"
          data-game-selected={selected('back') ? 'true' : undefined}
          onClick={onBack}
          onPointerDown={() => selectKey('back')}
          type="button"
        >
          Back
        </button>
      </div>

      {activeTab === 'stats' && (
        <div className="hunter-stat-grid">
          {statTiles.map((tile) => (
            <article
              className={`hunter-stat-tile ${selected(tile.key) ? 'game-selected' : ''}`}
              data-game-selected={selected(tile.key) ? 'true' : undefined}
              key={tile.key}
              onPointerDown={() => selectKey(tile.key)}
            >
              <span>{tile.label}</span>
              <strong>{tile.value}</strong>
              {tile.detail && <small>{tile.detail}</small>}
            </article>
          ))}
        </div>
      )}

      {activeTab === 'collection' && (
        <div className="collection-log-layout">
          <div className="collection-boss-list" aria-label="Bosses">
            {bosses.map((boss) => {
              return (
                <button
                  className={`collection-boss-button ${selectedBoss?.encounter.id === boss.encounter.id ? 'selected' : ''} ${selected(`boss:${boss.encounter.id}`) ? 'game-selected' : ''}`}
                  data-controller-nav="skip"
                  data-game-selected={selected(`boss:${boss.encounter.id}`) ? 'true' : undefined}
                  key={boss.encounter.id}
                  onClick={() => selectBoss(boss.encounter.id)}
                  onPointerDown={() => selectKey(`boss:${boss.encounter.id}`)}
                  type="button"
                >
                  <span>{bossInitials(boss.encounter.enemyName)}</span>
                  <strong>{boss.encounter.enemyName}</strong>
                </button>
              )
            })}
          </div>

          {selectedBoss && (
            <article className="collection-boss-detail">
              <div className="collection-drop-list">
                {collectionItems.map((item) => (
                  <button
                    className={`collection-drop-row collection-rarity-${item.rarity} ${item.quantity <= 0 ? 'missing' : 'owned'} ${selected(`item:${item.key}`) ? 'game-selected' : ''}`}
                    data-controller-nav="skip"
                    data-game-selected={selected(`item:${item.key}`) ? 'true' : undefined}
                    key={item.key}
                    onClick={() => setFocusedItemKey(item.key)}
                    onFocus={() => setFocusedItemKey(item.key)}
                    onPointerDown={() => selectKey(`item:${item.key}`)}
                    type="button"
                  >
                    <span>{item.glyph}</span>
                    <strong>{item.name}</strong>
                    <small>{item.chance}</small>
                    <b>x{item.quantity}</b>
                  </button>
                ))}
              </div>
            </article>
          )}
        </div>
      )}
    </section>
  )
}
