import { useEffect, useMemo, useRef, useState } from 'react'
import {
  breakdownItem,
  craftItem,
  equipItem,
  loadProfile,
  upgradeItem,
  type CharacterProfile,
  type EquipmentSlot,
  type Item,
} from '../profile'

const SLOT_LABELS: Record<EquipmentSlot, string> = {
  weapon: 'Weapon',
  helmet: 'Helmet',
  chest: 'Chest',
  gloves: 'Gloves',
  boots: 'Boots',
  pants: 'Pants',
  ring: 'Ring',
  necklace: 'Necklace',
  trinket: 'Trinket',
  component: 'Component',
}

const EQUIPMENT_LIST_PAGE_SIZE = 3
const CRAFTING_LIST_PAGE_SIZE = 6

type Props = {
  profile: CharacterProfile
  onBack?: () => void
  onUpdated: (profile: CharacterProfile) => void
  embedded?: boolean
}

export function EquipmentScreen({ profile, onBack, onUpdated, embedded = false }: Props) {
  const totalItemCount = profile.inventory.reduce(
    (total, item) => total + item.quantity,
    0,
  )
  const firstItem = profile.inventory.find((item) => !item.equipped)
    ?? profile.inventory[0]
  const [selectedItemId, setSelectedItemId] = useState<number | null>(
    firstItem?.id ?? null,
  )
  const [selectedSlot, setSelectedSlot] = useState<EquipmentSlot | null>(null)
  const [equipping, setEquipping] = useState(false)
  const [breakingDown, setBreakingDown] = useState(false)
  const [crafting, setCrafting] = useState(false)
  const [upgrading, setUpgrading] = useState(false)
  const [showSetBonuses, setShowSetBonuses] = useState(false)
  const [equipmentTab, setEquipmentTab] = useState<'equipment' | 'crafting'>('equipment')
  const [inventoryPage, setInventoryPage] = useState(0)
  const [recipePage, setRecipePage] = useState(0)
  const [message, setMessage] = useState('')
  const scrollRef = useRef<number>(0)
  const selectedItem = profile.inventory.find((item) => item.id === selectedItemId)
  const firstRecipe = profile.craftingRecipes.find((recipe) => recipe.canCraft)
    ?? profile.craftingRecipes[0]
  const [selectedRecipeId, setSelectedRecipeId] = useState<number | null>(
    firstRecipe?.id ?? null,
  )
  const selectedRecipe = profile.craftingRecipes.find((recipe) => recipe.id === selectedRecipeId)
  const selectedRecipeRequiresUpgrade = selectedRecipe
    ? profile.craftingRecipes.some((recipe) =>
      recipe.sourceEncounterId === selectedRecipe.sourceEncounterId
      && recipe.item.slot === selectedRecipe.item.slot
      && recipe.item.itemLevel < selectedRecipe.item.itemLevel,
    )
    : false
  const selectedItemRecipe = selectedItem
    ? profile.craftingRecipes.find((recipe) => recipe.item.id === selectedItem.id)
    : undefined
  const upgradeRecipe = selectedItem && selectedItemRecipe
    ? profile.craftingRecipes
      .filter((recipe) =>
        recipe.sourceEncounterId === selectedItemRecipe.sourceEncounterId
        && recipe.item.slot === selectedItem.slot
        && recipe.item.itemLevel > selectedItem.itemLevel,
      )
      .sort((left, right) => left.item.itemLevel - right.item.itemLevel)[0]
    : undefined
  const equippedBySlot = useMemo(
    () => new Map(
      profile.inventory
        .filter((item) => item.equipped)
        .map((item) => [item.slot, item]),
    ),
    [profile.inventory],
  )
  const comparisonItem = selectedItem
    ? equippedBySlot.get(selectedItem.slot)
    : undefined
  const visibleInventory = useMemo(
    () => selectedSlot
      ? profile.inventory.filter((item) => item.slot === selectedSlot)
      : profile.inventory,
    [profile.inventory, selectedSlot],
  )
  const visibleItemCount = visibleInventory.reduce(
    (total, item) => total + item.quantity,
    0,
  )
  const inventoryPageCount = Math.max(
    1,
    Math.ceil(visibleInventory.length / EQUIPMENT_LIST_PAGE_SIZE),
  )
  const inventoryPageItems = visibleInventory.slice(
    inventoryPage * EQUIPMENT_LIST_PAGE_SIZE,
    (inventoryPage + 1) * EQUIPMENT_LIST_PAGE_SIZE,
  )

  const [slotFilter, setSlotFilter] = useState<EquipmentSlot | 'all'>('all')
  const [levelFilter, setLevelFilter] = useState<number | null>(null)
  const availableLevels = useMemo(
    () => [...new Set(profile.craftingRecipes.map((r) => r.item.itemLevel))].sort((a, b) => b - a),
    [profile.craftingRecipes],
  )
  const filteredRecipes = useMemo(
    () => {
      let result = [...profile.craftingRecipes]
      if (slotFilter !== 'all') result = result.filter((r) => r.item.slot === slotFilter)
      if (levelFilter !== null) result = result.filter((r) => r.item.itemLevel === levelFilter)
      result.sort((a, b) => b.item.itemLevel - a.item.itemLevel)
      return result
    },
    [profile.craftingRecipes, slotFilter, levelFilter],
  )
  const recipePageCount = Math.max(
    1,
    Math.ceil(filteredRecipes.length / CRAFTING_LIST_PAGE_SIZE),
  )
  const recipePageItems = filteredRecipes.slice(
    recipePage * CRAFTING_LIST_PAGE_SIZE,
    (recipePage + 1) * CRAFTING_LIST_PAGE_SIZE,
  )

  useEffect(() => {
    window.scrollTo(0, scrollRef.current)
  }, [profile])

  useEffect(() => {
    setInventoryPage((current) => Math.min(current, inventoryPageCount - 1))
  }, [inventoryPageCount])

  useEffect(() => {
    setRecipePage((current) => Math.min(current, recipePageCount - 1))
  }, [recipePageCount])

  useEffect(() => {
    if (equipmentTab === 'crafting') {
      loadProfile().then((fresh) => onUpdated(fresh)).catch(() => {})
    }
  }, [equipmentTab])

  function saveScroll() {
    scrollRef.current = window.scrollY
  }

  async function equipSelected() {
    if (!selectedItem || selectedItem.equipped) return
    saveScroll()
    setEquipping(true)
    setMessage('')
    try {
      const updated = await equipItem(selectedItem.id)
      onUpdated(updated)
      setMessage(`${selectedItem.name} equipped.`)
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to equip item.')
    } finally {
      setEquipping(false)
    }
  }

  async function breakdownSelected() {
    if (!selectedItem) return
    saveScroll()
    setBreakingDown(true)
    setMessage('')
    try {
      const updated = await breakdownItem(selectedItem.id)
      onUpdated(updated)
      setMessage(
        selectedItem.quantity > 1
          ? `One duplicate ${selectedItem.name} broken down into components.`
          : `${selectedItem.name} broken down into components.`,
      )
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to break down item.')
    } finally {
      setBreakingDown(false)
    }
  }

  async function craftSelected() {
    if (!selectedRecipe) return
    saveScroll()
    setCrafting(true)
    setMessage('')
    try {
      const updated = await craftItem(selectedRecipe.id)
      onUpdated(updated)
      setSelectedItemId(selectedRecipe.item.id)
      setMessage(`${selectedRecipe.item.name} crafted.`)
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to craft item.')
    } finally {
      setCrafting(false)
    }
  }

  async function upgradeSelected() {
    if (!selectedItem || !upgradeRecipe) return
    saveScroll()
    setUpgrading(true)
    setMessage('')
    try {
      const updated = await upgradeItem(selectedItem.id)
      onUpdated(updated)
      setSelectedItemId(upgradeRecipe.item.id)
      setMessage(`${selectedItem.name} upgraded to ${upgradeRecipe.item.name}.`)
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to upgrade item.')
    } finally {
      setUpgrading(false)
    }
  }

  const content = (
    <>
      {!embedded && (
        <div className="screen-heading">
          <div>
            <p className="eyebrow">Character Loadout</p>
            <h1>Equipment</h1>
          </div>
          <button className="back-button" onClick={onBack} type="button">Back</button>
        </div>
      )}
      <div className="gear-summary">
        <div className="gear-character">
          <span style={{ borderColor: profile.character.themeColor, color: profile.character.themeColor }}>
            {profile.character.className[0]}
          </span>
          <div>
            <p className="eyebrow">{profile.character.className}</p>
            <h2>{profile.character.name}</h2>
          </div>
        </div>
        <GearStat value={profile.gearStats.averageItemLevel.toFixed(1)} label="Average Item Level" />
        <GearStat value={`+${profile.gearStats.healingPower}`} label="Healing Power" />
        <GearStat value={`+${profile.gearStats.maxResourceBonus}`} label={`Max ${profile.character.resourceName}`} />
      </div>

      <nav className="equipment-tabs">
        <button
          className={`equipment-tab ${equipmentTab === 'equipment' ? 'active' : ''}`}
          onClick={() => setEquipmentTab('equipment')}
          type="button"
        >
          Equipment
        </button>
        <button
          className={`equipment-tab ${equipmentTab === 'crafting' ? 'active' : ''}`}
          onClick={() => setEquipmentTab('crafting')}
          type="button"
        >
          Crafting
        </button>
      </nav>

      {equipmentTab === 'equipment' ? (
        <>
          <section className="item-comparison">
            {selectedItem ? (
              selectedItem.slot === 'component' ? (
                <>
                  <ItemDetail title="Crafting Component" item={selectedItem} />
                  <div className="equip-action">
                    <p className="component-note">Used in crafting.</p>
                  </div>
                </>
              ) : (
                <>
                  <ItemDetail title={selectedItem.equipped ? 'Selected Equipment' : 'Inventory Item'} item={selectedItem} />
                  <div className="comparison-arrow">vs</div>
                  {comparisonItem && comparisonItem.id !== selectedItem.id ? (
                    <ItemDetail title="Currently Equipped" item={comparisonItem} />
                  ) : (
                    <div className="item-detail empty-comparison">
                      <p className="eyebrow">Comparison</p>
                      <h2>{selectedItem.equipped ? 'Already Equipped' : 'Empty Slot'}</h2>
                    </div>
                  )}
                  <div className="equip-action">
                    <ComparisonDelta selected={selectedItem} equipped={comparisonItem} />
                    <button
                      className="primary-button"
                      disabled={selectedItem.equipped || equipping || breakingDown || upgrading}
                      onClick={equipSelected}
                      type="button"
                    >
                      {selectedItem.equipped ? 'Equipped' : equipping ? 'Equipping...' : 'Equip Item'}
                    </button>
                    {upgradeRecipe && (
                      <button
                        className="primary-button"
                        disabled={!upgradeRecipe.canCraft || equipping || breakingDown || upgrading}
                        onClick={upgradeSelected}
                        type="button"
                      >
                        {upgrading ? 'Upgrading...' : `Upgrade to iLvl ${upgradeRecipe.item.itemLevel}`}
                      </button>
                    )}
                    {(!selectedItem.equipped || selectedItem.quantity > 1) && (
                      <button
                        className="breakdown-button"
                        disabled={equipping || breakingDown || upgrading}
                        onClick={breakdownSelected}
                        type="button"
                      >
                        {breakingDown
                          ? 'Breaking Down...'
                          : selectedItem.quantity > 1
                            ? 'Break Down Duplicate'
                            : 'Break Down'}
                      </button>
                    )}
                  </div>
                </>
              )
            ) : (
              <p>Select an item to inspect it.</p>
            )}
          </section>

          <div className="equipment-layout">
            <section className="equipped-panel">
              <EquipmentHeading eyebrow="Currently Worn" title="Equipment Slots" />
              <div className="equipment-slots">
                {profile.equipmentSlots.map((slot) => {
                  const item = equippedBySlot.get(slot)
                  return (
                    <button
                      className={`${item ? `rarity-${item.rarity}` : 'empty'} ${selectedSlot === slot ? 'selected-slot' : ''}`}
                      key={slot}
                      onClick={() => {
                        setSelectedSlot(slot)
                        setInventoryPage(0)
                        const firstSlotItem = profile.inventory.find(
                          (candidate) => candidate.slot === slot,
                        )
                        setSelectedItemId(item?.id ?? firstSlotItem?.id ?? null)
                      }}
                      type="button"
                    >
                      <span>{item?.glyph ?? '-'}</span>
                      <div>
                        <strong>{item?.name ?? SLOT_LABELS[slot]}</strong>
                        <small>{SLOT_LABELS[slot]}{item ? ` - iLvl ${item.itemLevel}` : ' - Empty'}</small>
                      </div>
                      <div className="item-status">
                        {item && <i>Equipped</i>}
                      </div>
                    </button>
                  )
                })}
              </div>
            </section>

            <section className="inventory-panel">
              <EquipmentHeading
                eyebrow="Owned Items"
                title={selectedSlot ? `${SLOT_LABELS[selectedSlot]} Inventory` : 'Inventory'}
                detail={selectedSlot
                  ? `${visibleItemCount} items - ${visibleInventory.length} types`
                  : `${totalItemCount} items - ${profile.inventory.length} types`}
              />
              {selectedSlot && (
                <button
                  className="inventory-filter-clear"
                  onClick={() => {
                    setSelectedSlot(null)
                    setInventoryPage(0)
                  }}
                  type="button"
                >
                  Show All Items
                </button>
              )}
              <div className="inventory-list">
                {inventoryPageItems.map((item) => (
                  <button
                    className={`${selectedItemId === item.id ? 'selected' : ''} rarity-${item.rarity}`}
                    key={item.id}
                    onClick={() => setSelectedItemId(item.id)}
                    type="button"
                  >
                    <span>{item.glyph}</span>
                    <div>
                      <strong>{item.name}</strong>
                      <small>{SLOT_LABELS[item.slot]} - Item Level {item.itemLevel}</small>
                    </div>
                    <div className="item-status">
                      {item.equipped && <i>Equipped</i>}
                      {item.quantity > 1 && <i className="item-quantity">x{item.quantity}</i>}
                    </div>
                  </button>
                ))}
                {visibleInventory.length === 0 && (
                  <p className="inventory-empty">
                    No {SLOT_LABELS[selectedSlot ?? 'component'].toLowerCase()} items owned.
                  </p>
                )}
              </div>
              {visibleInventory.length > EQUIPMENT_LIST_PAGE_SIZE && (
                <ListPager
                  label={`Page ${inventoryPage + 1} / ${inventoryPageCount}`}
                  onNext={() => setInventoryPage((current) => Math.min(inventoryPageCount - 1, current + 1))}
                  onPrevious={() => setInventoryPage((current) => Math.max(0, current - 1))}
                  nextDisabled={inventoryPage >= inventoryPageCount - 1}
                  previousDisabled={inventoryPage <= 0}
                />
              )}
            </section>
          </div>
        </>
      ) : (
        <section className="crafting-panel">
          <EquipmentHeading
            eyebrow="Crafting"
            title="Recipes"
            detail={`${filteredRecipes.filter((recipe) => recipe.canCraft).length} ready`}
          />
          <div className="crafting-filter-bar">
            <select
              className="filter-select"
              value={slotFilter}
              onChange={(e) => {
                setSlotFilter(e.target.value as EquipmentSlot | 'all')
                setRecipePage(0)
              }}
            >
              <option value="all">All Slots</option>
              {(Object.entries(SLOT_LABELS) as [EquipmentSlot, string][]).map(([slot, label]) => (
                <option key={slot} value={slot}>{label}</option>
              ))}
            </select>
            <select
              className="filter-select"
              value={levelFilter ?? ''}
              onChange={(e) => {
                setLevelFilter(e.target.value === '' ? null : Number(e.target.value))
                setRecipePage(0)
              }}
            >
              <option value="">All Levels</option>
              {availableLevels.map((level) => (
                <option key={level} value={level}>Item Level {level}</option>
              ))}
            </select>
          </div>
          {filteredRecipes.length === 0 && (
            <p className="inventory-empty">No crafting recipes match filters.</p>
          )}
          {filteredRecipes.length > 0 && (
            <div className="crafting-layout">
              <div className="crafting-list">
                {recipePageItems.map((recipe) => (
                  <button
                    className={`${selectedRecipeId === recipe.id ? 'selected' : ''} rarity-${recipe.item.rarity}`}
                    key={recipe.id}
                    onClick={() => setSelectedRecipeId(recipe.id)}
                    type="button"
                  >
                    <span>{recipe.item.glyph}</span>
                    <div>
                      <strong>{recipe.item.name}</strong>
                      <small>
                        {SLOT_LABELS[recipe.item.slot]} - Item Level {recipe.item.itemLevel}
                        {recipe.item.setName ? ` - ${recipe.item.setName}` : ''}
                      </small>
                    </div>
                    <i>{recipe.canCraft ? 'Ready' : 'Needs materials'}</i>
                  </button>
                ))}
                {filteredRecipes.length > CRAFTING_LIST_PAGE_SIZE && (
                  <ListPager
                    label={`Page ${recipePage + 1} / ${recipePageCount}`}
                    onNext={() => setRecipePage((current) => Math.min(recipePageCount - 1, current + 1))}
                    onPrevious={() => setRecipePage((current) => Math.max(0, current - 1))}
                    nextDisabled={recipePage >= recipePageCount - 1}
                    previousDisabled={recipePage <= 0}
                  />
                )}
              </div>
              {selectedRecipe && (
                <div className={`crafting-detail rarity-${selectedRecipe.item.rarity}`}>
                  <ItemDetail title="Craft Output" item={{ ...selectedRecipe.item, quantity: 1, equipped: false }} />
                  <div className="crafting-components">
                    {selectedRecipe.components.map((component) => (
                      <div
                        className={component.owned >= component.quantity ? 'ready' : 'missing'}
                        key={component.item.id}
                      >
                        <span>{component.item.glyph}</span>
                        <strong>{component.item.name}</strong>
                        <i>{component.owned}/{component.quantity}</i>
                      </div>
                    ))}
                  </div>
                  <button
                    className="primary-button"
                    disabled={selectedRecipeRequiresUpgrade || !selectedRecipe.canCraft || crafting}
                    onClick={craftSelected}
                    type="button"
                  >
                    {crafting ? 'Crafting...' : selectedRecipeRequiresUpgrade ? 'Upgrade Existing Item' : 'Craft Item'}
                  </button>
                </div>
              )}
            </div>
          )}
        </section>
      )}

      {profile.setBonuses.length > 0 && (
        <section className="set-bonus-panel">
          <div className="equipment-heading toggle-heading">
            <div>
              <p className="eyebrow">Set Bonuses</p>
              <h2>Raid Sets</h2>
            </div>
            <button
              className="text-button"
              onClick={() => setShowSetBonuses((current) => !current)}
              type="button"
            >
              {showSetBonuses ? 'Hide Raid Sets' : 'Show Raid Sets'}
            </button>
          </div>
          {showSetBonuses && (
            <div className="set-bonus-list">
              {profile.setBonuses.map((bonus) => (
                <div className={bonus.active ? 'active' : ''} key={`${bonus.setId}-${bonus.requiredPieces}`}>
                  <strong>{bonus.requiredPieces} pieces</strong>
                  <span>{bonus.description}</span>
                  <i>{bonus.equippedPieces}/{bonus.requiredPieces}</i>
                </div>
              ))}
            </div>
          )}
        </section>
      )}

      <footer className="equipment-footer">
        {message || 'Equipment changes are saved immediately.'}
      </footer>
    </>
  )

  if (embedded) {
    return <div className="equipment-screen embedded-screen">{content}</div>
  }

  return (
    <section className="content-screen equipment-screen">
      {content}
    </section>
  )
}

function ListPager({
  label,
  nextDisabled,
  previousDisabled,
  onNext,
  onPrevious,
}: {
  label: string
  nextDisabled: boolean
  previousDisabled: boolean
  onNext: () => void
  onPrevious: () => void
}) {
  return (
    <div className="list-pager">
      <button disabled={previousDisabled} onClick={onPrevious} type="button">Prev</button>
      <span>{label}</span>
      <button disabled={nextDisabled} onClick={onNext} type="button">Next</button>
    </div>
  )
}

function GearStat({ value, label }: { value: string; label: string }) {
  return (
    <div className="gear-stat">
      <strong>{value}</strong>
      <span>{label}</span>
    </div>
  )
}

function EquipmentHeading({
  eyebrow,
  title,
  detail,
}: {
  eyebrow: string
  title: string
  detail?: string
}) {
  return (
    <div className="equipment-heading">
      <div><p className="eyebrow">{eyebrow}</p><h2>{title}</h2></div>
      {detail && <span>{detail}</span>}
    </div>
  )
}

function ItemDetail({ title, item }: { title: string; item: Item }) {
  return (
    <article className={`item-detail rarity-${item.rarity}`}>
      <p className="eyebrow">{title}</p>
      <div className="item-title">
        <span>{item.glyph}</span>
        <div>
          <h2>{item.name}</h2>
          <small>{SLOT_LABELS[item.slot]} - Item Level {item.itemLevel}</small>
        </div>
      </div>
      <p>{item.description}</p>
      {item.quantity > 1 && <p className="owned-quantity">Owned: {item.quantity}</p>}
      {item.slot !== 'component' && (
        <ul>
          <li>+{item.healingPower} Healing Power</li>
          <li>+{item.maxResourceBonus} Max Resource</li>
        </ul>
      )}
    </article>
  )
}

function ComparisonDelta({
  selected,
  equipped,
}: {
  selected: Item
  equipped?: Item
}) {
  const healingDelta = selected.healingPower - (equipped?.healingPower ?? 0)
  const resourceDelta = selected.maxResourceBonus - (equipped?.maxResourceBonus ?? 0)
  return (
    <div className="comparison-delta">
      <span className={healingDelta >= 0 ? 'positive' : 'negative'}>
        {healingDelta >= 0 ? '+' : ''}{healingDelta} Healing
      </span>
      <span className={resourceDelta >= 0 ? 'positive' : 'negative'}>
        {resourceDelta >= 0 ? '+' : ''}{resourceDelta} Resource
      </span>
    </div>
  )
}
