import { useEffect, useRef, useState } from 'react'
import {
  allocateTalent,
  resetTalents,
  type CharacterProfile,
  type Talent,
} from '../profile'

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

export function TalentScreen({ profile, onBack, onUpdated, embedded = false }: Props) {
  const [busyTalentId, setBusyTalentId] = useState<number | null>(null)
  const [talentPage, setTalentPage] = useState(0)
  const [resetting, setResetting] = useState(false)
  const [message, setMessage] = useState('')
  const scrollRef = useRef<number>(0)
  const gameClass = profile.classes.find(
    (candidate) => candidate.id === profile.character.classId,
  )!
  const classPointsSpent = gameClass.talents.reduce(
    (total, talent) => total + talent.rank,
    0,
  )
  const tiers = Array.from(
    new Set(gameClass.talents.map((talent) => talent.tier)),
  ).sort((a, b) => a - b)
  const tierPages = Array.from(
    { length: Math.ceil(tiers.length / 2) },
    (_, index) => tiers.slice(index * 2, index * 2 + 2),
  )
  const visibleTiers = tierPages[talentPage] ?? tierPages[0] ?? []

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

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

  function lowerTierPoints(talent: Talent) {
    return gameClass.talents
      .filter((candidate) => candidate.tier < talent.tier)
      .reduce((total, candidate) => total + candidate.rank, 0)
  }

  function lockReason(talent: Talent) {
    if (talent.rank >= talent.maxRank) return 'Maximum rank'

    const requiredTierPoints = (talent.tier - 1) * 5
    if (lowerTierPoints(talent) < requiredTierPoints) {
      return `Requires ${requiredTierPoints} earlier-tier points`
    }

    if (talent.prerequisiteTalentId) {
      const prerequisite = gameClass.talents.find(
        (candidate) => candidate.id === talent.prerequisiteTalentId,
      )
      if ((prerequisite?.rank ?? 0) < talent.prerequisiteRank) {
        return `Requires ${talent.prerequisiteName} rank ${talent.prerequisiteRank}`
      }
    }

    if (profile.character.talentPoints <= 0) return 'No points available'

    return ''
  }

  async function purchaseRank(talent: Talent) {
    saveScroll()
    setBusyTalentId(talent.id)
    setMessage('')
    try {
      const updated = await allocateTalent(talent.id)
      onUpdated(updated)
      setMessage(`${talent.name} increased to rank ${talent.rank + 1}.`)
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to allocate talent.')
    } finally {
      setBusyTalentId(null)
    }
  }

  async function refundTree() {
    saveScroll()
    setResetting(true)
    setMessage('')
    try {
      const updated = await resetTalents()
      onUpdated(updated)
      setMessage('All points in this talent tree were refunded.')
    } catch (reason) {
      setMessage(reason instanceof Error ? reason.message : 'Unable to reset talents.')
    } finally {
      setResetting(false)
    }
  }

  const content = (
    <>
      {!embedded && (
        <div className="screen-heading">
          <div>
            <p className="eyebrow">Character Growth</p>
            <h1>Talents</h1>
          </div>
          <button className="back-button" onClick={onBack} type="button">Back</button>
        </div>
      )}
      <div className="talent-toolbar">
        <div className="talent-class-summary">
          <span style={{ borderColor: gameClass.themeColor, color: gameClass.themeColor }}>
            {gameClass.name[0]}
          </span>
          <div>
            <p className="eyebrow">{gameClass.name} Tree</p>
            <h2>Shape Your Healing Style</h2>
          </div>
        </div>
        <div className="talent-points">
          <strong>{profile.character.talentPoints}</strong>
          <span>Available</span>
          <small>{classPointsSpent} spent in this tree</small>
        </div>
      </div>

      <nav className="talent-page-tabs" role="tablist" aria-label="Talent tier pages">
        {tierPages.map((pageTiers, index) => (
          <button
            aria-selected={talentPage === index}
            className={talentPage === index ? 'active' : ''}
            key={pageTiers.join('-')}
            onClick={() => setTalentPage(index)}
            role="tab"
            type="button"
          >
            Tiers {pageTiers[0]}-{pageTiers[pageTiers.length - 1]}
          </button>
        ))}
      </nav>

      <div className="talent-tree">
        {visibleTiers.map((tier) => {
          const requiredPoints = (tier - 1) * 5
          return (
            <section className="talent-tier" key={tier}>
              <div className="tier-label">
                <span>Tier {tier}</span>
                <small>
                  {tier === 1 ? 'Open' : `${requiredPoints} earlier-tier points`}
                </small>
              </div>
              <div className="tier-talents">
                {gameClass.talents
                  .filter((talent) => talent.tier === tier)
                  .sort((a, b) => a.branch - b.branch)
                  .map((talent) => {
                    const reason = lockReason(talent)
                    const isBusy = busyTalentId === talent.id
                    return (
                      <article
                        className={`talent-node ${reason ? 'locked' : 'available'} ${talent.rank > 0 ? 'invested' : ''}`}
                        key={talent.id}
                        style={{ gridColumn: talent.branch }}
                      >
                        <div className="talent-node-header">
                          <span>{talent.glyph}</span>
                          <div>
                            <strong>{talent.name}</strong>
                            <small>Rank {talent.rank}/{talent.maxRank}</small>
                          </div>
                        </div>
                        <p>{talent.description}</p>
                        <div className="rank-pips">
                          {Array.from({ length: talent.maxRank }, (_, index) => (
                            <i className={index < talent.rank ? 'filled' : ''} key={index} />
                          ))}
                        </div>
                        <button
                          disabled={Boolean(reason) || isBusy}
                          onClick={() => purchaseRank(talent)}
                          type="button"
                        >
                          {isBusy ? 'Saving...' : reason || 'Add Rank'}
                        </button>
                      </article>
                    )
                  })}
              </div>
            </section>
          )
        })}
      </div>

      <footer className="talent-footer">
        <span>{message || 'Talent changes are saved immediately.'}</span>
        <button
          className="text-button"
          disabled={classPointsSpent === 0 || resetting}
          onClick={refundTree}
          type="button"
        >
          {resetting ? 'Refunding...' : 'Reset Tree'}
        </button>
      </footer>
    </>
  )

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

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