import { type CSSProperties, type FormEvent, useEffect, useMemo, useRef, useState } from 'react'
import { Navigate, useNavigate } from 'react-router-dom'
import { ArcadeNameInput } from '../features/end-of-game/ArcadeNameInput'
import { EndOfGameActions } from '../features/end-of-game/EndOfGameActions'
import { ResultsSummaryBar } from '../features/end-of-game/ResultsSummaryBar'
import { dominantJudgment, gradeDataAttr, letterFromOverride } from '../features/end-of-game/result-utils'
import { submitLeaderboardScore } from '../features/end-of-game/submitLeaderboardScore'
import { useScoreReveal } from '../features/end-of-game/useScoreReveal'
import { lighten, withAlpha } from '../features/song-select/color-utils'
import { type LetterGrade, letterGradeFromJudgments } from '../lib/judgmentGrade'
import { ROUTE_PATHS } from '../app/route-paths'
import { playSound, SFX_BUTTON_DEFAULT } from '../lib/sounds'
import { useGameStatsStore } from '../stores/game-stats/store'
import { useLeaderboardStore } from '../stores/leaderboard/store'
import styles from './EndOfGamePage.module.css'

export type { LetterGrade, GameEndState } from '../lib/judgmentGrade'

export type EndOfGamePageProps = {
  score?: number
  perfect?: number
  good?: number
  miss?: number
  /** Optional override; normally the grade is computed from judgment counts */
  grade?: LetterGrade | string
}

/** Arcade-style name length (one slot per character; increase if you need longer names) */
const ARCADE_NAME_MAX = 16

const DEFAULT_SCORE = 98500
const DEFAULT_PERFECT = 36
const DEFAULT_GOOD = 8
const DEFAULT_MISS = 1

const ACCENT_HEX = '#d946ef'

export function EndOfGamePage({
  score: scoreProp,
  perfect: perfectProp,
  good: goodProp,
  miss: missProp,
  grade: gradeProp,
}: EndOfGamePageProps) {
  const navigate = useNavigate()
  const nameInputRef = useRef<HTMLInputElement>(null)

  const currentSong = useGameStatsStore((state) => state.currentSong)
  const scoreStore = useGameStatsStore((state) => state.score)
  const perfectStore = useGameStatsStore((state) => state.perfectHits)
  const goodStore = useGameStatsStore((state) => state.goodHits)
  const missStore = useGameStatsStore((state) => state.misses)
  const gradeStore = useGameStatsStore((state) => state.computedGradeLetter)
  const setHighlight = useLeaderboardStore((state) => state.setHighlight)
  const hasStoreResults = currentSong != null || scoreStore > 0 || perfectStore + goodStore + missStore > 0
  const hasAnyResultInput = hasStoreResults || scoreProp !== undefined

  const score = scoreProp ?? (hasStoreResults ? scoreStore : DEFAULT_SCORE)
  const perfect = perfectProp ?? (hasStoreResults ? perfectStore : DEFAULT_PERFECT)
  const good = goodProp ?? (hasStoreResults ? goodStore : DEFAULT_GOOD)
  const miss = missProp ?? (hasStoreResults ? missStore : DEFAULT_MISS)

  const { displayScore, showGrade } = useScoreReveal(score)

  const gradeLetter = useMemo<LetterGrade>(() => {
    if (gradeProp !== undefined) return letterFromOverride(String(gradeProp))
    if (scoreProp === undefined && perfectProp === undefined && goodProp === undefined && missProp === undefined) {
      return gradeStore
    }
    return letterGradeFromJudgments(perfect, good, miss)
  }, [gradeProp, perfect, good, miss, gradeStore, scoreProp, perfectProp, goodProp, missProp])

  const gradeKey = gradeDataAttr(gradeLetter)

  const totalNotes = useMemo(() => perfect + good + miss, [perfect, good, miss])

  const judgmentLead = useMemo(
    () => dominantJudgment(perfect, good, miss),
    [perfect, good, miss],
  )

  const cssVars = useMemo(
    () =>
      ({
        '--endgame-accent': ACCENT_HEX,
        '--endgame-highlight': lighten(ACCENT_HEX, 0.42),
      }) as CSSProperties,
    [],
  )

  const summaryBarStyle = useMemo(
    () =>
      ({
        backgroundColor: withAlpha(ACCENT_HEX, 0.32),
        borderColor: withAlpha(ACCENT_HEX, 0.88),
      }) as CSSProperties,
    [],
  )

  const nameBarStyle = useMemo(
    () =>
      ({
        backgroundColor: withAlpha(ACCENT_HEX, 0.28),
        borderColor: withAlpha(ACCENT_HEX, 0.85),
      }) as CSSProperties,
    [],
  )

  const confirmBtnStyle = useMemo(
    () =>
      ({
        backgroundColor: lighten(ACCENT_HEX, 0.38),
        color: ACCENT_HEX,
      }) as CSSProperties,
    [],
  )

  const [username, setUsername] = useState('')
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    if (!showGrade) return
    const t = window.setTimeout(() => nameInputRef.current?.focus(), 520)
    return () => window.clearTimeout(t)
  }, [showGrade])

  if (!hasAnyResultInput) return <Navigate to={ROUTE_PATHS.intro} replace />

  function handleNameChange(raw: string) {
    const upper = raw.toUpperCase().replace(/[^A-Z0-9\s\-_]/g, '')
    if (upper.length <= ARCADE_NAME_MAX) setUsername(upper)
  }

  async function handleSubmit(e: FormEvent) {
    e.preventDefault()
    setError(null)
    const trimmed = username.trim()
    if (!trimmed) {
      setError('Please enter a name.')
      return
    }

    setSubmitting(true)
    const { error: insertError } = await submitLeaderboardScore(trimmed, score, gradeLetter)

    setSubmitting(false)

    if (insertError) {
      setError(insertError.message || 'Could not save your score.')
      return
    }

    setHighlight({ username: trimmed, score })

    navigate(ROUTE_PATHS.leaderboard)
  }

  function handleSkip() {
    navigate(ROUTE_PATHS.leaderboard)
  }

  return (
    <div className={styles.root} style={cssVars}>
      <div className={styles.hud} aria-hidden="true">
        <span className={`${styles.hudCorner} ${styles.hudCornerTl}`} />
        <span className={`${styles.hudCorner} ${styles.hudCornerTr}`} />
        <span className={`${styles.hudCorner} ${styles.hudCornerBl}`} />
        <span className={`${styles.hudCorner} ${styles.hudCornerBr}`} />
        <div className={styles.hudCounter}>RESULTS</div>
        <div className={styles.hudMetaLeft}>STAGE CLEAR</div>
        <div className={styles.hudMetaRight}>{showGrade ? `RANK ${gradeLetter}` : 'RANK —'}</div>
      </div>

      <div className={styles.inner}>
        <h1 className={`${styles.screenTitle} font-title`}>GAME OVER</h1>

        <section className={styles.scoreHero} aria-label="Final score">
          <span className={`${styles.scoreHeroLabel} font-caption`}>FINAL SCORE</span>
          <p className={`${styles.scoreHeroValue} font-display`}>{displayScore.toLocaleString()}</p>
        </section>

        {showGrade ? (
          <ResultsSummaryBar
            gradeKey={gradeKey}
            gradeLetter={gradeLetter}
            perfect={perfect}
            good={good}
            miss={miss}
            totalNotes={totalNotes}
            judgmentLead={judgmentLead}
            style={summaryBarStyle}
          />
        ) : null}

        <form className={styles.form} onSubmit={handleSubmit} noValidate>
          <ArcadeNameInput
            maxLength={ARCADE_NAME_MAX}
            username={username}
            inputRef={nameInputRef}
            style={nameBarStyle}
            onNameChange={handleNameChange}
          />

          <button
            type="submit"
            className={`${styles.arcadeConfirm} font-title`}
            style={confirmBtnStyle}
            disabled={submitting}
            onClick={() => {
              playSound(SFX_BUTTON_DEFAULT)
            }}
          >
            {submitting ? 'SAVING…' : 'SUBMIT SCORE'}
          </button>

          {error ? (
            <p className={styles.error} role="alert">
              {error}
            </p>
          ) : null}
        </form>

        <EndOfGameActions
          onSkip={() => {
            playSound(SFX_BUTTON_DEFAULT)
            handleSkip()
          }}
          onPlayAgain={() => {
            playSound(SFX_BUTTON_DEFAULT)
            navigate(ROUTE_PATHS.songSelection)
          }}
          onHome={() => {
            playSound(SFX_BUTTON_DEFAULT)
            navigate(ROUTE_PATHS.home)
          }}
        />
      </div>
    </div>
  )
}
