import { useCallback, useEffect, useState } from 'react'
import { AuthScreen } from './components/AuthScreen'
import IWantToHeal1App from './modes/iwt1/IWantToHeal1App'
import { IWantToHeal2App } from './modes/iwt2/IWantToHeal2App'
import { useGameAction } from './input'
import {
  loadAuthSession,
  type AuthSession,
} from './profile'

type GameVersion = 'iwt1' | 'iwt2'

const GAME_OPTIONS: Array<{
  version: GameVersion
  title: string
  label: string
  description: string
  glyph: string
}> = [
  {
    version: 'iwt1',
    title: 'I Want To Heal 1',
    label: 'Classic Healer Runs',
    description: 'Original dungeon, raid, roguelike, PvP, gear, talents, and collection progression.',
    glyph: 'I',
  },
  {
    version: 'iwt2',
    title: 'I Want To Heal 2',
    label: '2D Boss Arena',
    description: 'Move through boss arenas with a visible party, analog movement, projectiles, and separate progression.',
    glyph: 'II',
  },
]

function App() {
  const [selectedVersion, setSelectedVersion] = useState<GameVersion | null>(null)
  const [selectedIndex, setSelectedIndex] = useState(0)
  const [authSession, setAuthSession] = useState<AuthSession | null>(null)
  const [authChecked, setAuthChecked] = useState(false)
  const [serverMessage, setServerMessage] = useState('')

  useEffect(() => {
    let cancelled = false
    loadAuthSession()
      .then((session) => {
        if (cancelled) return
        setAuthSession(session.account && session.profile ? session : null)
      })
      .catch((reason: unknown) => {
        if (cancelled) return
        setServerMessage(
          reason instanceof Error
            ? `${reason.message} Offline play is still available.`
            : 'Unable to reach the server. Offline play is still available.',
        )
      })
      .finally(() => {
        if (!cancelled) setAuthChecked(true)
      })
    return () => {
      cancelled = true
    }
  }, [])

  const acceptSession = useCallback((session: AuthSession) => {
    setAuthSession(session)
    setSelectedVersion(null)
    setServerMessage('')
  }, [])

  const clearAuthSession = useCallback(() => {
    setAuthSession(null)
    setSelectedVersion(null)
  }, [])

  useGameAction((action, device) => {
    if (!authSession || selectedVersion || device !== 'controller') return
    if (action === 'navigateLeft' || action === 'navigateUp') {
      setSelectedIndex((current) => Math.max(0, current - 1))
    } else if (action === 'navigateRight' || action === 'navigateDown') {
      setSelectedIndex((current) => Math.min(GAME_OPTIONS.length - 1, current + 1))
    } else if (action === 'confirm') {
      setSelectedVersion(GAME_OPTIONS[selectedIndex].version)
    }
  })

  if (!authChecked) {
    return (
      <main className="game-shell">
        <section className="message-panel">
          <p className="eyebrow">Opening Chronicle</p>
          <h1>Loading...</h1>
        </section>
      </main>
    )
  }

  if (!authSession) {
    return (
      <AuthScreen
        onAuthenticated={acceptSession}
        serverMessage={serverMessage}
      />
    )
  }

  if (selectedVersion === 'iwt1') {
    return (
      <IWantToHeal1App
        initialSession={authSession}
        onAuthenticationCleared={clearAuthSession}
        onBackToGameSelect={() => setSelectedVersion(null)}
      />
    )
  }

  if (selectedVersion === 'iwt2') {
    return (
      <IWantToHeal2App
        onlineBackupsAvailable={authSession.account?.id !== -1}
        onBackToGameSelect={() => setSelectedVersion(null)}
      />
    )
  }

  return (
    <main className="game-shell game-version-shell">
      <section className="game-version-screen" data-game-nav-active="true">
        <div className="game-version-heading">
          <p className="eyebrow">Select Game</p>
          <h1>I Want To Heal</h1>
        </div>
        <div className="game-version-grid">
          {GAME_OPTIONS.map((option, index) => (
            <button
              className={`game-version-card ${selectedIndex === index ? 'game-selected' : ''}`}
              data-controller-nav="skip"
              data-game-selected={selectedIndex === index ? 'true' : undefined}
              key={option.version}
              onClick={() => setSelectedVersion(option.version)}
              onPointerDown={() => setSelectedIndex(index)}
              type="button"
            >
              <span>{option.glyph}</span>
              <div>
                <strong>{option.title}</strong>
                <small>{option.label}</small>
                <p>{option.description}</p>
              </div>
            </button>
          ))}
        </div>
      </section>
    </main>
  )
}

export default App
