import 'package:flutter/foundation.dart'
    show kIsWeb, defaultTargetPlatform, TargetPlatform;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show SchedulerBinding, SchedulerPhase;
import 'package:flutter/services.dart' show KeyDownEvent, LogicalKeyboardKey;

import 'package:asciineverdie/data/game_text_l10n.dart' as game_l10n;
import 'package:asciineverdie/data/skill_data.dart';
import 'package:asciineverdie/data/story_data.dart';
import 'package:asciineverdie/l10n/app_localizations.dart';
import 'package:asciineverdie/src/core/animation/ascii_animation_type.dart';
import 'package:asciineverdie/src/core/engine/story_service.dart';
import 'package:asciineverdie/src/core/model/combat_event.dart';
import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/skill.dart';
import 'package:asciineverdie/src/core/notification/notification_service.dart';
import 'package:asciineverdie/src/core/util/pq_logic.dart' as pq_logic;
import 'package:asciineverdie/src/features/game/game_session_controller.dart';
import 'package:asciineverdie/src/features/hall_of_fame/hall_of_fame_screen.dart';
import 'package:asciineverdie/src/features/game/widgets/cinematic_view.dart';
import 'package:asciineverdie/src/features/game/widgets/combat_log.dart';
import 'package:asciineverdie/src/features/game/widgets/death_overlay.dart';
import 'package:asciineverdie/src/features/game/widgets/victory_overlay.dart';
import 'package:asciineverdie/src/features/game/widgets/hp_mp_bar.dart';
import 'package:asciineverdie/src/features/game/widgets/notification_overlay.dart';
import 'package:asciineverdie/src/features/game/widgets/stats_panel.dart';
import 'package:asciineverdie/src/features/game/widgets/equipment_stats_panel.dart';
import 'package:asciineverdie/src/features/game/widgets/potion_inventory_panel.dart';
import 'package:asciineverdie/src/features/game/widgets/task_progress_panel.dart';
import 'package:asciineverdie/src/features/game/widgets/active_buff_panel.dart';
import 'package:asciineverdie/src/features/game/layouts/mobile_carousel_layout.dart';
import 'package:asciineverdie/src/features/settings/settings_screen.dart';
import 'package:asciineverdie/src/features/game/widgets/statistics_dialog.dart';
import 'package:asciineverdie/src/features/game/widgets/help_dialog.dart';
import 'package:asciineverdie/src/core/storage/settings_repository.dart';
import 'package:asciineverdie/src/core/audio/audio_service.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';

/// 게임 진행 화면 (Main.dfm 기반 3패널 레이아웃)
///
/// Phase 7: colorTheme 제거됨, 고정 4색 팔레트 사용
class GamePlayScreen extends StatefulWidget {
  const GamePlayScreen({
    super.key,
    required this.controller,
    this.audioService,
    this.forceCarouselLayout = false,
    this.forceDesktopLayout = false,
    this.onThemeModeChange,
    this.currentThemeMode = ThemeMode.system,
  });

  final GameSessionController controller;

  /// 오디오 서비스 (BGM/SFX 재생)
  final AudioService? audioService;

  /// 테스트 모드: 웹에서도 모바일 캐로셀 레이아웃 강제 사용
  final bool forceCarouselLayout;

  /// 테스트 모드: 모바일에서도 데스크톱 3패널 레이아웃 강제 사용
  final bool forceDesktopLayout;

  /// 테마 모드 변경 콜백
  final void Function(ThemeMode mode)? onThemeModeChange;

  /// 현재 테마 모드
  final ThemeMode currentThemeMode;

  @override
  State<GamePlayScreen> createState() => _GamePlayScreenState();
}

class _GamePlayScreenState extends State<GamePlayScreen>
    with WidgetsBindingObserver {
  AsciiAnimationType? _specialAnimation;

  // Phase 8: 알림 서비스 (Notification Service)
  late final NotificationService _notificationService;

  // Phase 9: 스토리 서비스 (Story Service)
  late final StoryService _storyService;
  StoryAct _lastAct = StoryAct.prologue;
  bool _showingCinematic = false;

  // Phase 8: 전투 로그 (Combat Log)
  final List<CombatLogEntry> _combatLogEntries = [];
  String _lastTaskCaption = '';

  // 이전 상태 추적 (레벨업/퀘스트/Act 완료 감지용)
  int _lastLevel = 0;
  int _lastQuestCount = 0;
  int _lastPlotStageCount = 0;

  // 전투 이벤트 추적 (마지막 처리된 이벤트 수)
  int _lastProcessedEventCount = 0;

  // 오디오 상태 추적 (TaskType 기반)
  bool _wasInBattleTask = false;

  // 사운드 볼륨 상태 (모바일 설정 UI용)
  double _bgmVolume = 0.7;
  double _sfxVolume = 0.8;

  void _checkSpecialEvents(GameState state) {
    // Phase 8: 태스크 변경 시 로그 추가
    final currentCaption = state.progress.currentTask.caption;
    if (currentCaption.isNotEmpty && currentCaption != _lastTaskCaption) {
      _addCombatLog(currentCaption, CombatLogType.normal);
      _lastTaskCaption = currentCaption;
      // 새 태스크 시작 시 이벤트 카운터 리셋
      _lastProcessedEventCount = 0;
    }

    // 전투 이벤트 처리 (Combat Events)
    _processCombatEvents(state);

    // 오디오: TaskType 변경 시 BGM 전환 (애니메이션과 동기화)
    _updateBgmForTaskType(state);

    // 레벨업 감지
    if (state.traits.level > _lastLevel && _lastLevel > 0) {
      _specialAnimation = AsciiAnimationType.levelUp;
      _notificationService.showLevelUp(state.traits.level);
      _addCombatLog(
        '${game_l10n.uiLevelUp} Lv.${state.traits.level}',
        CombatLogType.levelUp,
      );
      // 오디오: 레벨업 SFX (플레이어 채널)
      widget.audioService?.playPlayerSfx('level_up');
      _resetSpecialAnimationAfterFrame();

      // Phase 9: Act 변경 감지 (레벨 기반)
      final newAct = getActForLevel(state.traits.level);
      if (newAct != _lastAct && !_showingCinematic) {
        _lastAct = newAct;

        // 엔딩은 controller.isComplete 상태에서 VictoryOverlay로 처리
        // 일반 Act 전환 시에만 시네마틱 표시
        if (newAct != StoryAct.ending) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (mounted) _showCinematicForAct(newAct);
          });
        }
      }
    }
    _lastLevel = state.traits.level;

    // 퀘스트 완료 감지
    if (state.progress.questCount > _lastQuestCount && _lastQuestCount > 0) {
      _specialAnimation = AsciiAnimationType.questComplete;
      // 완료된 퀘스트 이름 가져오기
      final completedQuest = state.progress.questHistory
          .where((q) => q.isComplete)
          .lastOrNull;
      if (completedQuest != null) {
        _notificationService.showQuestComplete(completedQuest.caption);
        _addCombatLog(
          game_l10n.uiQuestComplete(completedQuest.caption),
          CombatLogType.questComplete,
        );
      }
      // 오디오: 퀘스트 완료 SFX (플레이어 채널)
      widget.audioService?.playPlayerSfx('quest_complete');
      _resetSpecialAnimationAfterFrame();
    }
    _lastQuestCount = state.progress.questCount;

    // Act 완료 감지 (plotStageCount 증가)
    // plotStageCount: 1=프롤로그 진행, 2=프롤로그 완료, 3=Act1 완료...
    // 완료된 스테이지 인덱스 = plotStageCount - 2 (0=프롤로그, 1=Act1, ...)
    if (state.progress.plotStageCount > _lastPlotStageCount &&
        _lastPlotStageCount > 0) {
      _specialAnimation = AsciiAnimationType.actComplete;
      _notificationService.showActComplete(state.progress.plotStageCount - 2);
      _resetSpecialAnimationAfterFrame();
    }
    _lastPlotStageCount = state.progress.plotStageCount;
  }

  /// Phase 8: 전투 로그 추가 (Add Combat Log Entry)
  void _addCombatLog(String message, CombatLogType type) {
    _combatLogEntries.add(
      CombatLogEntry(message: message, timestamp: DateTime.now(), type: type),
    );
    // 최대 50개 유지
    if (_combatLogEntries.length > 50) {
      _combatLogEntries.removeAt(0);
    }
  }

  /// 전투 이벤트를 로그로 변환 (Convert Combat Events to Log)
  void _processCombatEvents(GameState state) {
    final combat = state.progress.currentCombat;
    if (combat == null || !combat.isActive) {
      _lastProcessedEventCount = 0;
      return;
    }

    final events = combat.recentEvents;
    if (events.isEmpty || events.length <= _lastProcessedEventCount) {
      return;
    }

    // 새 이벤트만 처리
    final newEvents = events.skip(_lastProcessedEventCount);
    for (final event in newEvents) {
      final (message, type) = _formatCombatEvent(event);
      _addCombatLog(message, type);

      // 오디오: 전투 이벤트에 따른 SFX 재생
      _playCombatEventSfx(event);
    }

    _lastProcessedEventCount = events.length;
  }

  /// 초기 BGM 재생 (게임 시작/로드 시)
  ///
  /// TaskType 기반으로 BGM 결정 (애니메이션과 동기화)
  void _playInitialBgm(GameState state) {
    final audio = widget.audioService;
    if (audio == null) return;

    final taskType = state.progress.currentTask.type;
    final isInBattleTask = taskType == TaskType.kill;

    if (isInBattleTask) {
      // 전투 태스크: 보스 여부에 따라 BGM 선택
      final monsterLevel = state.progress.currentTask.monsterLevel ?? 0;
      final playerLevel = state.traits.level;
      final isBoss = monsterLevel >= playerLevel + 5;

      if (isBoss) {
        audio.playBgm('boss');
      } else {
        audio.playBgm('battle');
      }
    } else {
      // 비전투 태스크: 마을 BGM
      audio.playBgm('town');
    }

    _wasInBattleTask = isInBattleTask;
  }

  /// TaskType 기반 BGM 전환 (애니메이션과 동기화)
  ///
  /// 애니메이션은 TaskType으로 결정되므로, BGM도 동일한 기준 사용
  /// 전환 감지 외에도 현재 BGM이 TaskType과 일치하는지 검증
  void _updateBgmForTaskType(GameState state) {
    final audio = widget.audioService;
    if (audio == null) return;

    final taskType = state.progress.currentTask.type;
    final isInBattleTask = taskType == TaskType.kill;

    // 전투 태스크 상태 결정
    if (isInBattleTask) {
      // 전투 태스크: 보스 여부에 따라 BGM 선택
      final monsterLevel = state.progress.currentTask.monsterLevel ?? 0;
      final playerLevel = state.traits.level;
      final isBoss = monsterLevel >= playerLevel + 5;
      final expectedBgm = isBoss ? 'boss' : 'battle';

      // 전환 시점이거나 현재 BGM이 일치하지 않으면 재생
      if (!_wasInBattleTask || audio.currentBgm != expectedBgm) {
        audio.playBgm(expectedBgm);
      }
    } else if (_wasInBattleTask || audio.currentBgm == 'battle' || audio.currentBgm == 'boss') {
      // 전투 태스크 종료 또는 BGM 불일치: 마을 BGM으로 복귀
      audio.playBgm('town');
    }

    _wasInBattleTask = isInBattleTask;
  }

  /// 전투 이벤트별 SFX 재생 (채널 분리)
  ///
  /// 플레이어 이펙트와 몬스터 이펙트를 별도 채널에서 재생하여
  /// 사운드 충돌을 방지하고 완료를 보장합니다.
  void _playCombatEventSfx(CombatEvent event) {
    final audio = widget.audioService;
    if (audio == null) return;

    switch (event.type) {
      // 플레이어 채널: 플레이어가 발생시키는 이펙트
      case CombatEventType.playerAttack:
        audio.playPlayerSfx('attack');
      case CombatEventType.playerSkill:
        audio.playPlayerSfx('skill');
      case CombatEventType.playerHeal:
      case CombatEventType.playerPotion:
      case CombatEventType.potionDrop:
        audio.playPlayerSfx('item');
      case CombatEventType.playerBuff:
      case CombatEventType.playerDebuff:
        audio.playPlayerSfx('skill');

      // 몬스터 채널: 몬스터가 발생시키는 이펙트 (플레이어 피격)
      case CombatEventType.monsterAttack:
        audio.playMonsterSfx('hit');

      // SFX 없음
      case CombatEventType.dotTick:
        // DOT 틱은 SFX 없음 (너무 자주 발생)
        break;
      case CombatEventType.playerEvade:
      case CombatEventType.monsterEvade:
      case CombatEventType.playerBlock:
      case CombatEventType.playerParry:
        // 회피/방어는 별도 SFX 없음
        break;
    }
  }

  /// 전투 이벤트를 메시지와 타입으로 변환
  (String, CombatLogType) _formatCombatEvent(CombatEvent event) {
    final target = event.targetName ?? '';
    // 스킬/포션 이름 번역 (전역 로케일 사용)
    final skillName = event.skillName != null
        ? game_l10n.translateSpell(event.skillName!)
        : '';
    return switch (event.type) {
      CombatEventType.playerAttack =>
        event.isCritical
            ? (
                game_l10n.combatCritical(event.damage, target),
                CombatLogType.critical,
              )
            : (
                game_l10n.combatYouHit(target, event.damage),
                CombatLogType.damage,
              ),
      CombatEventType.monsterAttack => (
        game_l10n.combatMonsterHitsYou(target, event.damage),
        CombatLogType.monsterAttack,
      ),
      CombatEventType.playerEvade => (
        game_l10n.combatYouEvaded(target),
        CombatLogType.evade,
      ),
      CombatEventType.monsterEvade => (
        game_l10n.combatMonsterEvaded(target),
        CombatLogType.evade,
      ),
      CombatEventType.playerBlock => (
        game_l10n.combatBlocked(event.damage),
        CombatLogType.block,
      ),
      CombatEventType.playerParry => (
        game_l10n.combatParried(event.damage),
        CombatLogType.parry,
      ),
      CombatEventType.playerSkill =>
        event.isCritical
            ? (
                game_l10n.combatSkillCritical(skillName, event.damage),
                CombatLogType.critical,
              )
            : (
                game_l10n.combatSkillDamage(skillName, event.damage),
                CombatLogType.spell,
              ),
      CombatEventType.playerHeal => (
        game_l10n.combatSkillHeal(
          skillName.isNotEmpty ? skillName : game_l10n.uiHeal,
          event.healAmount,
        ),
        CombatLogType.heal,
      ),
      CombatEventType.playerBuff => (
        game_l10n.combatBuffActivated(skillName),
        CombatLogType.buff,
      ),
      CombatEventType.playerDebuff => (
        game_l10n.combatDebuffApplied(skillName, target),
        CombatLogType.debuff,
      ),
      CombatEventType.dotTick => (
        game_l10n.combatDotTick(skillName, event.damage),
        CombatLogType.dotTick,
      ),
      CombatEventType.playerPotion => (
        game_l10n.combatPotionUsed(skillName, event.healAmount, target),
        CombatLogType.potion,
      ),
      CombatEventType.potionDrop => (
        game_l10n.combatPotionDrop(skillName),
        CombatLogType.potionDrop,
      ),
    };
  }

  /// Phase 9: Act 시네마틱 표시 (Show Act Cinematic)
  Future<void> _showCinematicForAct(StoryAct act) async {
    if (_showingCinematic) return;

    _showingCinematic = true;
    // 게임 일시 정지
    await widget.controller.pause(saveOnStop: false);

    if (mounted) {
      await showActCinematic(context, act);
    }

    // 게임 재개
    if (mounted) {
      await widget.controller.resume();
    }
    _showingCinematic = false;
  }

  /// VictoryOverlay 완료 후 명예의 전당 화면으로 이동
  void _handleVictoryComplete() {
    Navigator.of(context).pushReplacement(
      MaterialPageRoute<void>(
        builder: (context) => const HallOfFameScreen(),
      ),
    );
  }

  void _resetSpecialAnimationAfterFrame() {
    // 다음 프레임에서 리셋 (AsciiAnimationCard가 값을 받은 후)
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        setState(() {
          _specialAnimation = null;
        });
      }
    });
  }

  @override
  void initState() {
    super.initState();
    _notificationService = NotificationService();
    _storyService = StoryService();
    widget.controller.addListener(_onControllerChanged);
    WidgetsBinding.instance.addObserver(this);

    // 초기 상태 설정
    final state = widget.controller.state;
    if (state != null) {
      _lastLevel = state.traits.level;
      _lastQuestCount = state.progress.questCount;
      _lastPlotStageCount = state.progress.plotStageCount;
      _lastAct = getActForLevel(state.traits.level);

      // 초기 BGM 재생 (TaskType 기반, _wasInBattleTask도 함께 설정)
      _playInitialBgm(state);
    } else {
      // 상태가 없으면 기본 마을 BGM
      widget.audioService?.playBgm('town');
    }

    // 누적 통계 로드
    widget.controller.loadCumulativeStats();

    // 오디오 볼륨 초기화
    _initAudioVolumes();
  }

  /// 오디오 볼륨 초기화 (설정에서 로드)
  Future<void> _initAudioVolumes() async {
    final audio = widget.audioService;
    if (audio != null) {
      _bgmVolume = audio.bgmVolume;
      _sfxVolume = audio.sfxVolume;
      if (mounted) setState(() {});
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 로케일 변경 시 게임 l10n 동기화 (시네마틱 번역 등에 필수)
    final locale = Localizations.localeOf(context);
    game_l10n.setGameLocale(locale.languageCode);
  }

  @override
  void dispose() {
    _notificationService.dispose();
    _storyService.dispose();
    WidgetsBinding.instance.removeObserver(this);
    widget.controller.removeListener(_onControllerChanged);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState appState) {
    super.didChangeAppLifecycleState(appState);

    // 모바일 환경 확인 (iOS/Android)
    final isMobile = !kIsWeb &&
        (defaultTargetPlatform == TargetPlatform.iOS ||
            defaultTargetPlatform == TargetPlatform.android);

    // 앱이 백그라운드로 가거나 비활성화될 때
    if (appState == AppLifecycleState.paused ||
        appState == AppLifecycleState.inactive ||
        appState == AppLifecycleState.detached) {
      // 저장
      _saveGameState();

      // 모바일: 게임 일시정지 + 전체 오디오 정지
      if (isMobile) {
        widget.controller.pause(saveOnStop: false);
        widget.audioService?.pauseAll();
      }
    }

    // 모바일: 앱이 포그라운드로 돌아올 때 전체 재로드
    if (appState == AppLifecycleState.resumed && isMobile) {
      widget.audioService?.resumeAll();
      _reloadGameScreen();
    }
  }

  /// 모바일 재진입 시 전체 화면 재로드
  Future<void> _reloadGameScreen() async {
    // 세이브 파일에서 다시 로드
    await widget.controller.loadAndStart(cheatsEnabled: widget.controller.cheatsEnabled);

    if (!mounted) return;

    // 화면 재생성 (상태 초기화)
    Navigator.of(context).pushReplacement(
      MaterialPageRoute<void>(
        builder: (_) => GamePlayScreen(
          controller: widget.controller,
          audioService: widget.audioService,
          currentThemeMode: widget.currentThemeMode,
          onThemeModeChange: widget.onThemeModeChange,
        ),
      ),
    );
  }

  Future<void> _saveGameState() async {
    final currentState = widget.controller.state;
    if (currentState == null || !widget.controller.isRunning) return;

    await widget.controller.saveManager.saveState(currentState);
  }

  /// 뒤로가기 시 저장 확인 다이얼로그
  Future<bool> _onPopInvoked() async {
    final l10n = L10n.of(context);
    final shouldPop = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(l10n.exitGame),
        content: Text(l10n.saveProgressQuestion),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: Text(l10n.cancel),
          ),
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(true);
            },
            child: Text(l10n.exitWithoutSaving),
          ),
          FilledButton(
            onPressed: () async {
              await _saveGameState();
              if (context.mounted) {
                Navigator.of(context).pop(true);
              }
            },
            child: Text(l10n.saveAndExit),
          ),
        ],
      ),
    );
    return shouldPop ?? false;
  }

  void _onControllerChanged() {
    final state = widget.controller.state;
    if (state != null) {
      _checkSpecialEvents(state);
    }

    // WASM 안정성: 프레임 빌드 중이면 다음 프레임까지 대기
    if (SchedulerBinding.instance.schedulerPhase ==
        SchedulerPhase.persistentCallbacks) {
      SchedulerBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() {});
        }
      });
    } else {
      setState(() {});
    }
  }

  /// 캐로셀 레이아웃 사용 여부 판단
  ///
  /// - forceDesktopLayout (테스트 모드) 활성화 시 데스크톱 레이아웃 사용
  /// - forceCarouselLayout (테스트 모드) 활성화 시 캐로셀 레이아웃 사용
  /// - 실제 모바일 플랫폼 (iOS/Android) 시 캐로셀 사용
  bool _shouldUseCarouselLayout(BuildContext context) {
    // 테스트 모드: 데스크톱 레이아웃 강제
    if (widget.forceDesktopLayout) return false;

    // 테스트 모드: 캐로셀 레이아웃 강제
    if (widget.forceCarouselLayout) return true;

    // 웹에서는 3패널 레이아웃 사용 (테스트 모드가 아닌 경우)
    if (kIsWeb) return false;

    // 모바일 플랫폼(iOS/Android)에서는 캐로셀 사용
    final platform = defaultTargetPlatform;
    return platform == TargetPlatform.iOS || platform == TargetPlatform.android;
  }

  /// 통계 다이얼로그 표시
  void _showStatisticsDialog(BuildContext context) {
    StatisticsDialog.show(
      context,
      session: widget.controller.sessionStats,
      cumulative: widget.controller.cumulativeStats,
    );
  }

  /// 설정 화면 표시
  void _showSettingsScreen(BuildContext context) {
    final settingsRepo = SettingsRepository();
    SettingsScreen.show(
      context,
      settingsRepository: settingsRepo,
      currentThemeMode: widget.currentThemeMode,
      onThemeModeChange: (mode) {
        widget.onThemeModeChange?.call(mode);
      },
      onLocaleChange: (locale) async {
        // 안전한 언어 변경: 전체 화면 재생성
        final navigator = Navigator.of(this.context);
        await widget.controller.pause(saveOnStop: true);
        game_l10n.setGameLocale(locale);
        if (mounted) {
          await widget.controller.resume();
          navigator.pushReplacement(
            MaterialPageRoute<void>(
              builder: (_) => GamePlayScreen(
                controller: widget.controller,
                audioService: widget.audioService,
                currentThemeMode: widget.currentThemeMode,
                onThemeModeChange: widget.onThemeModeChange,
              ),
            ),
          );
        }
      },
      onBgmVolumeChange: (volume) {
        setState(() => _bgmVolume = volume);
        widget.audioService?.setBgmVolume(volume);
      },
      onSfxVolumeChange: (volume) {
        setState(() => _sfxVolume = volume);
        widget.audioService?.setSfxVolume(volume);
      },
    );
  }

  /// 부활 처리 핸들러
  Future<void> _handleResurrect() async {
    // 1. 부활 애니메이션 먼저 설정 (DeathOverlay 사라지기 전에)
    setState(() {
      _specialAnimation = AsciiAnimationType.resurrection;
    });

    // 2. 부활 처리 (HP/MP 회복, 장비 구매 - 게임 재개 없음)
    // 이 시점에서 isDead가 false가 되고 DeathOverlay가 사라지지만,
    // _specialAnimation이 이미 설정되어 있어 부활 애니메이션이 표시됨
    await widget.controller.resurrect();

    // 3. 애니메이션 종료 후 게임 재개
    final duration = getSpecialAnimationDuration(
      AsciiAnimationType.resurrection,
    );
    Future.delayed(Duration(milliseconds: duration), () async {
      if (mounted) {
        // 먼저 게임 재개 (status를 running으로 변경)
        // 이렇게 해야 setState 시 UI가 '일시정지' 상태로 보이지 않음
        await widget.controller.resumeAfterResurrection();
        if (mounted) {
          setState(() {
            _specialAnimation = null;
          });
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final state = widget.controller.state;
    if (state == null) {
      return const Scaffold(body: Center(child: CircularProgressIndicator()));
    }

    // 로케일 변경 시 전체 위젯 트리 강제 리빌드를 위한 Key
    final localeKey = ValueKey(game_l10n.currentGameLocale);

    // 캐로셀 레이아웃 사용 여부 확인
    if (_shouldUseCarouselLayout(context)) {
      return NotificationOverlay(
        key: localeKey,
        notificationService: _notificationService,
        child: PopScope(
          canPop: false,
          onPopInvokedWithResult: (didPop, result) async {
            if (didPop) return;
            final shouldPop = await _onPopInvoked();
            if (shouldPop && context.mounted) {
              await widget.controller.pause(saveOnStop: false);
              if (context.mounted) {
                Navigator.of(context).pop();
              }
            }
          },
          child: Stack(
            children: [
              MobileCarouselLayout(
                state: state,
                combatLogEntries: _combatLogEntries,
                speedMultiplier: widget.controller.loop?.speedMultiplier ?? 1,
                onSpeedCycle: () {
                  widget.controller.loop?.cycleSpeed();
                  setState(() {});
                },
                // 특수 애니메이션 중에는 일시정지 상태로 표시하지 않음
                isPaused: !widget.controller.isRunning && _specialAnimation == null,
                onPauseToggle: () async {
                  await widget.controller.togglePause();
                  setState(() {});
                },
                onSave: _saveGameState,
                onExit: () async {
                  final shouldExit = await _onPopInvoked();
                  if (shouldExit && context.mounted) {
                    await widget.controller.pause(saveOnStop: false);
                    if (context.mounted) {
                      Navigator.of(context).pop();
                    }
                  }
                },
                notificationService: _notificationService,
                specialAnimation: _specialAnimation,
                onLanguageChange: (locale) async {
                  // navigator 참조를 async gap 전에 저장
                  final navigator = Navigator.of(context);
                  // 1. 현재 상태 저장
                  await widget.controller.pause(saveOnStop: true);
                  // 2. 로케일 변경
                  game_l10n.setGameLocale(locale);
                  // 3. 화면 재생성 (전체 UI 재구성)
                  if (context.mounted) {
                    await widget.controller.resume();
                    navigator.pushReplacement(
                      MaterialPageRoute<void>(
                        builder: (_) => GamePlayScreen(
                          controller: widget.controller,
                          audioService: widget.audioService,
                          currentThemeMode: widget.currentThemeMode,
                          onThemeModeChange: widget.onThemeModeChange,
                        ),
                      ),
                    );
                  }
                },
                onDeleteSaveAndNewGame: () async {
                  // 게임 루프 중지
                  await widget.controller.pause(saveOnStop: false);
                  // 세이브 파일 삭제
                  await widget.controller.saveManager.deleteSave();
                  // 캐릭터 생성 화면으로 돌아가기
                  if (context.mounted) {
                    Navigator.of(context).pop();
                  }
                },
                currentThemeMode: widget.currentThemeMode,
                onThemeModeChange: widget.onThemeModeChange,
                // 사운드 설정
                bgmVolume: _bgmVolume,
                sfxVolume: _sfxVolume,
                onBgmVolumeChange: (volume) {
                  setState(() => _bgmVolume = volume);
                  widget.audioService?.setBgmVolume(volume);
                },
                onSfxVolumeChange: (volume) {
                  setState(() => _sfxVolume = volume);
                  widget.audioService?.setSfxVolume(volume);
                },
                // 통계 및 도움말
                onShowStatistics: () => _showStatisticsDialog(context),
                onShowHelp: () => HelpDialog.show(context),
                // 치트 (디버그 모드)
                cheatsEnabled: widget.controller.cheatsEnabled,
                onCheatTask: () => widget.controller.loop?.cheatCompleteTask(),
                onCheatQuest: () => widget.controller.loop?.cheatCompleteQuest(),
                onCheatPlot: () => widget.controller.loop?.cheatCompletePlot(),
              ),
              // 사망 오버레이
              if (state.isDead && state.deathInfo != null)
                DeathOverlay(
                  deathInfo: state.deathInfo!,
                  traits: state.traits,
                  onResurrect: _handleResurrect,
                ),
              // 승리 오버레이 (게임 클리어)
              if (widget.controller.isComplete)
                VictoryOverlay(
                  traits: state.traits,
                  stats: state.stats,
                  progress: state.progress,
                  elapsedMs: state.skillSystem.elapsedMs,
                  onComplete: _handleVictoryComplete,
                ),
            ],
          ),
        ),
      );
    }

    // 기존 데스크톱 레이아웃 (레트로 스타일)
    return NotificationOverlay(
      key: localeKey,
      notificationService: _notificationService,
      child: PopScope(
        canPop: false,
        onPopInvokedWithResult: (didPop, result) async {
          if (didPop) return;
          final shouldPop = await _onPopInvoked();
          if (shouldPop && context.mounted) {
            await widget.controller.pause(saveOnStop: false);
            if (context.mounted) {
              Navigator.of(context).pop();
            }
          }
        },
        // 웹/데스크톱 키보드 단축키 지원
        child: Focus(
          autofocus: true,
          onKeyEvent: (node, event) => _handleKeyboardShortcut(event, context),
          child: Scaffold(
          backgroundColor: RetroColors.deepBrown,
          appBar: AppBar(
            backgroundColor: RetroColors.darkBrown,
            title: Text(
              L10n.of(context).progressQuestTitle(state.traits.name),
              style: const TextStyle(
                fontFamily: 'PressStart2P',
                fontSize: 12,
                color: RetroColors.gold,
              ),
            ),
            actions: [
              // 치트 버튼 (디버그용)
              if (widget.controller.cheatsEnabled) ...[
                IconButton(
                  icon: const Text('L+1'),
                  tooltip: L10n.of(context).levelUp,
                  onPressed: () => widget.controller.loop?.cheatCompleteTask(),
                ),
                IconButton(
                  icon: const Text('Q!'),
                  tooltip: L10n.of(context).completeQuest,
                  onPressed: () => widget.controller.loop?.cheatCompleteQuest(),
                ),
                IconButton(
                  icon: const Text('P!'),
                  tooltip: L10n.of(context).completePlot,
                  onPressed: () => widget.controller.loop?.cheatCompletePlot(),
                ),
              ],
              // 통계 버튼
              IconButton(
                icon: const Icon(Icons.bar_chart),
                tooltip: game_l10n.uiStatistics,
                onPressed: () => _showStatisticsDialog(context),
              ),
              // 도움말 버튼
              IconButton(
                icon: const Icon(Icons.help_outline),
                tooltip: game_l10n.uiHelp,
                onPressed: () => HelpDialog.show(context),
              ),
              // 설정 버튼
              IconButton(
                icon: const Icon(Icons.settings),
                tooltip: game_l10n.uiSettings,
                onPressed: () => _showSettingsScreen(context),
              ),
            ],
          ),
          body: Stack(
            children: [
              // 메인 게임 UI
              Column(
                children: [
                  // 상단: ASCII 애니메이션 + Task Progress (Phase 7: 고정 4색 팔레트)
                  TaskProgressPanel(
                    progress: state.progress,
                    speedMultiplier:
                        widget.controller.loop?.speedMultiplier ?? 1,
                    onSpeedCycle: () {
                      widget.controller.loop?.cycleSpeed();
                      setState(() {});
                    },
                    // 특수 애니메이션 중에는 일시정지 상태로 표시하지 않음
                    isPaused: !widget.controller.isRunning && _specialAnimation == null,
                    onPauseToggle: () async {
                      await widget.controller.togglePause();
                      setState(() {});
                    },
                    specialAnimation: _specialAnimation,
                    weaponName: state.equipment.weapon,
                    shieldName: state.equipment.shield,
                    characterLevel: state.traits.level,
                    monsterLevel: state.progress.currentTask.monsterLevel,
                    latestCombatEvent:
                        state.progress.currentCombat?.recentEvents.lastOrNull,
                    raceId: state.traits.raceId,
                  ),

                  // 메인 3패널 영역
                  Expanded(
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        // 좌측 패널: Character Sheet
                        Expanded(flex: 2, child: _buildCharacterPanel(state)),

                        // 중앙 패널: Equipment/Inventory
                        Expanded(flex: 3, child: _buildEquipmentPanel(state)),

                        // 우측 패널: Plot/Quest
                        Expanded(flex: 2, child: _buildQuestPanel(state)),
                      ],
                    ),
                  ),
                ],
              ),

              // Phase 4: 사망 오버레이 (Death Overlay)
              if (state.isDead && state.deathInfo != null)
                DeathOverlay(
                  deathInfo: state.deathInfo!,
                  traits: state.traits,
                  onResurrect: _handleResurrect,
                ),
              // 승리 오버레이 (게임 클리어)
              if (widget.controller.isComplete)
                VictoryOverlay(
                  traits: state.traits,
                  stats: state.stats,
                  progress: state.progress,
                  elapsedMs: state.skillSystem.elapsedMs,
                  onComplete: _handleVictoryComplete,
                ),
            ],
          ),
        ),
        ),
      ),
    );
  }

  /// 키보드 단축키 핸들러 (웹/데스크톱)
  /// Space: 일시정지/재개, S: 속도 변경, H: 도움말, Esc: 설정
  KeyEventResult _handleKeyboardShortcut(KeyEvent event, BuildContext context) {
    // KeyDown 이벤트만 처리
    if (event is! KeyDownEvent) return KeyEventResult.ignored;

    final key = event.logicalKey;

    // Space: 일시정지/재개
    if (key == LogicalKeyboardKey.space) {
      widget.controller.togglePause();
      setState(() {});
      return KeyEventResult.handled;
    }

    // S: 속도 변경
    if (key == LogicalKeyboardKey.keyS) {
      widget.controller.loop?.cycleSpeed();
      setState(() {});
      return KeyEventResult.handled;
    }

    // H 또는 F1: 도움말
    if (key == LogicalKeyboardKey.keyH || key == LogicalKeyboardKey.f1) {
      HelpDialog.show(context);
      return KeyEventResult.handled;
    }

    // Escape: 설정
    if (key == LogicalKeyboardKey.escape) {
      _showSettingsScreen(context);
      return KeyEventResult.handled;
    }

    // I: 통계
    if (key == LogicalKeyboardKey.keyI) {
      _showStatisticsDialog(context);
      return KeyEventResult.handled;
    }

    return KeyEventResult.ignored;
  }

  /// 좌측 패널: Character Sheet (Traits, Stats, Experience, Spells)
  Widget _buildCharacterPanel(GameState state) {
    final l10n = L10n.of(context);
    return Card(
      margin: const EdgeInsets.all(4),
      color: RetroColors.panelBg,
      shape: RoundedRectangleBorder(
        side: const BorderSide(color: RetroColors.panelBorderOuter, width: 2),
        borderRadius: BorderRadius.circular(0),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildPanelHeader(l10n.characterSheet),

          // Traits 목록
          _buildSectionHeader(l10n.traits),
          _buildTraitsList(state),

          // Stats 목록 (Phase 8: 애니메이션 변화 표시)
          _buildSectionHeader(l10n.stats),
          Expanded(flex: 2, child: StatsPanel(stats: state.stats)),

          // Phase 8: HP/MP 바 (사망 위험 시 깜빡임, 전투 중 몬스터 HP 표시)
          // 전투 중에는 전투 스탯의 HP/MP 사용, 비전투 시 기본 스탯 사용
          HpMpBar(
            hpCurrent:
                state.progress.currentCombat?.playerStats.hpCurrent ??
                state.stats.hp,
            hpMax:
                state.progress.currentCombat?.playerStats.hpMax ??
                state.stats.hpMax,
            mpCurrent:
                state.progress.currentCombat?.playerStats.mpCurrent ??
                state.stats.mp,
            mpMax:
                state.progress.currentCombat?.playerStats.mpMax ??
                state.stats.mpMax,
            // 전투 중일 때 몬스터 HP 정보 전달
            monsterHpCurrent:
                state.progress.currentCombat?.monsterStats.hpCurrent,
            monsterHpMax: state.progress.currentCombat?.monsterStats.hpMax,
            monsterName: state.progress.currentCombat?.monsterStats.name,
          ),

          // Experience 바
          _buildSectionHeader(l10n.experience),
          _buildProgressBar(
            state.progress.exp.position,
            state.progress.exp.max,
            Colors.blue,
            tooltip:
                '${state.progress.exp.max - state.progress.exp.position} '
                '${l10n.xpNeededForNextLevel}',
          ),

          // 스킬 (Skills - SpellBook 기반)
          _buildSectionHeader(l10n.spellBook),
          Expanded(flex: 3, child: _buildSkillsList(state)),

          // 활성 버프 (Active Buffs)
          _buildSectionHeader(game_l10n.uiBuffs),
          Expanded(
            child: ActiveBuffPanel(
              activeBuffs: state.skillSystem.activeBuffs,
              currentMs: state.skillSystem.elapsedMs,
            ),
          ),
        ],
      ),
    );
  }

  /// 중앙 패널: Equipment/Inventory
  Widget _buildEquipmentPanel(GameState state) {
    final l10n = L10n.of(context);
    return Card(
      margin: const EdgeInsets.all(4),
      color: RetroColors.panelBg,
      shape: RoundedRectangleBorder(
        side: const BorderSide(color: RetroColors.panelBorderOuter, width: 2),
        borderRadius: BorderRadius.circular(0),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildPanelHeader(l10n.equipment),

          // Equipment 목록 (확장 가능 스탯 패널)
          Expanded(
            flex: 2,
            child: EquipmentStatsPanel(equipment: state.equipment),
          ),

          // Inventory
          _buildPanelHeader(l10n.inventory),
          Expanded(child: _buildInventoryList(state)),

          // Potions (물약 인벤토리)
          _buildSectionHeader(game_l10n.uiPotions),
          Expanded(
            child: PotionInventoryPanel(
              inventory: state.potionInventory,
              usedInBattle:
                  state.progress.currentCombat?.usedPotionTypes ?? const {},
            ),
          ),

          // Encumbrance 바
          _buildSectionHeader(l10n.encumbrance),
          _buildProgressBar(
            state.progress.encumbrance.position,
            state.progress.encumbrance.max,
            Colors.orange,
          ),

          // Phase 8: 전투 로그 (Combat Log)
          _buildPanelHeader(l10n.combatLog),
          Expanded(flex: 2, child: CombatLog(entries: _combatLogEntries)),
        ],
      ),
    );
  }

  /// 우측 패널: Plot/Quest
  Widget _buildQuestPanel(GameState state) {
    final l10n = L10n.of(context);
    return Card(
      margin: const EdgeInsets.all(4),
      color: RetroColors.panelBg,
      shape: RoundedRectangleBorder(
        side: const BorderSide(color: RetroColors.panelBorderOuter, width: 2),
        borderRadius: BorderRadius.circular(0),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildPanelHeader(l10n.plotDevelopment),

          // Plot 목록
          Expanded(child: _buildPlotList(state)),

          // Plot 바
          _buildProgressBar(
            state.progress.plot.position,
            state.progress.plot.max,
            Colors.purple,
            tooltip: state.progress.plot.max > 0
                ? '${pq_logic.roughTime(state.progress.plot.max - state.progress.plot.position)} remaining'
                : null,
          ),

          _buildPanelHeader(l10n.quests),

          // Quest 목록
          Expanded(child: _buildQuestList(state)),

          // Quest 바
          _buildProgressBar(
            state.progress.quest.position,
            state.progress.quest.max,
            Colors.green,
            tooltip: state.progress.quest.max > 0
                ? l10n.percentComplete(
                    100 *
                        state.progress.quest.position ~/
                        state.progress.quest.max,
                  )
                : null,
          ),
        ],
      ),
    );
  }

  Widget _buildPanelHeader(String title) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
      decoration: const BoxDecoration(
        color: RetroColors.darkBrown,
        border: Border(
          bottom: BorderSide(color: RetroColors.gold, width: 2),
        ),
      ),
      child: Text(
        title.toUpperCase(),
        style: const TextStyle(
          fontFamily: 'PressStart2P',
          fontSize: 8,
          fontWeight: FontWeight.bold,
          color: RetroColors.gold,
        ),
      ),
    );
  }

  Widget _buildSectionHeader(String title) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      child: Text(
        title.toUpperCase(),
        style: const TextStyle(
          fontFamily: 'PressStart2P',
          fontSize: 6,
          color: RetroColors.textDisabled,
        ),
      ),
    );
  }

  /// 레트로 스타일 세그먼트 프로그레스 바
  Widget _buildProgressBar(
    int position,
    int max,
    Color color, {
    String? tooltip,
  }) {
    final progress = max > 0 ? (position / max).clamp(0.0, 1.0) : 0.0;
    const segmentCount = 20;
    final filledSegments = (progress * segmentCount).round();

    final bar = Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      child: Container(
        height: 12,
        decoration: BoxDecoration(
          color: color.withValues(alpha: 0.15),
          border: Border.all(color: RetroColors.panelBorderOuter, width: 1),
        ),
        child: Row(
          children: List.generate(segmentCount, (index) {
            final isFilled = index < filledSegments;
            return Expanded(
              child: Container(
                decoration: BoxDecoration(
                  color: isFilled ? color : color.withValues(alpha: 0.1),
                  border: Border(
                    right: index < segmentCount - 1
                        ? BorderSide(
                            color: RetroColors.panelBorderOuter.withValues(alpha: 0.3),
                            width: 1,
                          )
                        : BorderSide.none,
                  ),
                ),
              ),
            );
          }),
        ),
      ),
    );

    if (tooltip != null && tooltip.isNotEmpty) {
      return Tooltip(message: tooltip, child: bar);
    }
    return bar;
  }

  Widget _buildTraitsList(GameState state) {
    final l10n = L10n.of(context);
    final traits = [
      (l10n.traitName, state.traits.name),
      (l10n.traitRace, GameDataL10n.getRaceName(context, state.traits.race)),
      (l10n.traitClass, GameDataL10n.getKlassName(context, state.traits.klass)),
      (l10n.traitLevel, '${state.traits.level}'),
    ];

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
      child: Column(
        children: traits.map((t) {
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 1),
            child: Row(
              children: [
                SizedBox(
                  width: 50,
                  child: Text(
                    t.$1.toUpperCase(),
                    style: const TextStyle(
                      fontFamily: 'PressStart2P',
                      fontSize: 6,
                      color: RetroColors.textDisabled,
                    ),
                  ),
                ),
                Expanded(
                  child: Text(
                    t.$2,
                    style: const TextStyle(
                      fontFamily: 'PressStart2P',
                      fontSize: 7,
                      color: RetroColors.textLight,
                    ),
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
              ],
            ),
          );
        }).toList(),
      ),
    );
  }

  /// 통합 스킬 목록 (SpellBook 기반)
  ///
  /// 스펠 이름, 랭크, 스킬 타입, 쿨타임 표시
  Widget _buildSkillsList(GameState state) {
    if (state.spellBook.spells.isEmpty) {
      return Center(
        child: Text(
          L10n.of(context).noSpellsYet,
          style: const TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 7,
            color: RetroColors.textDisabled,
          ),
        ),
      );
    }

    return ListView.builder(
      itemCount: state.spellBook.spells.length,
      padding: const EdgeInsets.symmetric(horizontal: 8),
      itemBuilder: (context, index) {
        final spell = state.spellBook.spells[index];
        final skill = SkillData.getSkillBySpellName(spell.name);
        final spellName = GameDataL10n.getSpellName(context, spell.name);

        // 쿨타임 상태 확인
        final skillState = skill != null
            ? state.skillSystem.getSkillState(skill.id)
            : null;
        final isOnCooldown =
            skillState != null &&
            !skillState.isReady(state.skillSystem.elapsedMs, skill!.cooldownMs);

        return _SkillRow(
          spellName: spellName,
          rank: spell.rank,
          skill: skill,
          isOnCooldown: isOnCooldown,
        );
      },
    );
  }

  Widget _buildInventoryList(GameState state) {
    final l10n = L10n.of(context);
    if (state.inventory.items.isEmpty) {
      return Center(
        child: Text(
          l10n.goldAmount(state.inventory.gold),
          style: const TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 7,
            color: RetroColors.gold,
          ),
        ),
      );
    }

    return ListView.builder(
      itemCount: state.inventory.items.length + 1, // +1 for gold
      padding: const EdgeInsets.symmetric(horizontal: 8),
      itemBuilder: (context, index) {
        if (index == 0) {
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 2),
            child: Row(
              children: [
                const Icon(Icons.monetization_on, size: 10, color: RetroColors.gold),
                const SizedBox(width: 4),
                Expanded(
                  child: Text(
                    l10n.gold.toUpperCase(),
                    style: const TextStyle(
                      fontFamily: 'PressStart2P',
                      fontSize: 6,
                      color: RetroColors.gold,
                    ),
                  ),
                ),
                Text(
                  '${state.inventory.gold}',
                  style: const TextStyle(
                    fontFamily: 'PressStart2P',
                    fontSize: 7,
                    color: RetroColors.gold,
                  ),
                ),
              ],
            ),
          );
        }
        final item = state.inventory.items[index - 1];
        // 아이템 이름 번역
        final translatedName = GameDataL10n.translateItemString(
          context,
          item.name,
        );
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 1),
          child: Row(
            children: [
              Expanded(
                child: Text(
                  translatedName,
                  style: const TextStyle(
                    fontFamily: 'PressStart2P',
                    fontSize: 6,
                    color: RetroColors.textLight,
                  ),
                  overflow: TextOverflow.ellipsis,
                ),
              ),
              Text(
                '${item.count}',
                style: const TextStyle(
                  fontFamily: 'PressStart2P',
                  fontSize: 6,
                  color: RetroColors.cream,
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildPlotList(GameState state) {
    // 플롯 단계를 표시 (Act I, Act II, ...)
    final l10n = L10n.of(context);
    final plotCount = state.progress.plotStageCount;
    if (plotCount == 0) {
      return Center(
        child: Text(
          l10n.prologue.toUpperCase(),
          style: const TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 7,
            color: RetroColors.textDisabled,
          ),
        ),
      );
    }

    return ListView.builder(
      itemCount: plotCount,
      padding: const EdgeInsets.symmetric(horizontal: 8),
      itemBuilder: (context, index) {
        final isCompleted = index < plotCount - 1;
        final isCurrent = index == plotCount - 1;
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 1),
          child: Row(
            children: [
              Icon(
                isCompleted
                    ? Icons.check_box
                    : (isCurrent ? Icons.arrow_right : Icons.check_box_outline_blank),
                size: 12,
                color: isCompleted
                    ? RetroColors.expGreen
                    : (isCurrent ? RetroColors.gold : RetroColors.textDisabled),
              ),
              const SizedBox(width: 4),
              Expanded(
                child: Text(
                  index == 0 ? l10n.prologue : l10n.actNumber(_toRoman(index)),
                  style: TextStyle(
                    fontFamily: 'PressStart2P',
                    fontSize: 6,
                    color: isCompleted
                        ? RetroColors.textDisabled
                        : (isCurrent ? RetroColors.gold : RetroColors.textLight),
                    decoration: isCompleted
                        ? TextDecoration.lineThrough
                        : TextDecoration.none,
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildQuestList(GameState state) {
    final l10n = L10n.of(context);
    final questHistory = state.progress.questHistory;

    if (questHistory.isEmpty) {
      return Center(
        child: Text(
          l10n.noActiveQuests.toUpperCase(),
          style: const TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 7,
            color: RetroColors.textDisabled,
          ),
        ),
      );
    }

    // 원본처럼 퀘스트 히스토리를 리스트로 표시
    // 완료된 퀘스트는 체크박스, 현재 퀘스트는 화살표
    return ListView.builder(
      itemCount: questHistory.length,
      padding: const EdgeInsets.symmetric(horizontal: 8),
      itemBuilder: (context, index) {
        final quest = questHistory[index];
        final isCurrentQuest =
            index == questHistory.length - 1 && !quest.isComplete;

        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 1),
          child: Row(
            children: [
              Icon(
                isCurrentQuest
                    ? Icons.arrow_right
                    : (quest.isComplete
                        ? Icons.check_box
                        : Icons.check_box_outline_blank),
                size: 12,
                color: isCurrentQuest
                    ? RetroColors.gold
                    : (quest.isComplete
                        ? RetroColors.expGreen
                        : RetroColors.textDisabled),
              ),
              const SizedBox(width: 4),
              Expanded(
                child: Text(
                  quest.caption,
                  style: TextStyle(
                    fontFamily: 'PressStart2P',
                    fontSize: 6,
                    color: isCurrentQuest
                        ? RetroColors.gold
                        : (quest.isComplete
                            ? RetroColors.textDisabled
                            : RetroColors.textLight),
                    decoration: quest.isComplete
                        ? TextDecoration.lineThrough
                        : TextDecoration.none,
                  ),
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  /// 로마 숫자 변환 (간단 버전)
  String _toRoman(int number) {
    const romanNumerals = [
      (1000, 'M'),
      (900, 'CM'),
      (500, 'D'),
      (400, 'CD'),
      (100, 'C'),
      (90, 'XC'),
      (50, 'L'),
      (40, 'XL'),
      (10, 'X'),
      (9, 'IX'),
      (5, 'V'),
      (4, 'IV'),
      (1, 'I'),
    ];

    var result = '';
    var remaining = number;
    for (final (value, numeral) in romanNumerals) {
      while (remaining >= value) {
        result += numeral;
        remaining -= value;
      }
    }
    return result;
  }
}

/// 스킬 행 위젯
///
/// 스펠 이름, 랭크, 스킬 타입 아이콘, 쿨타임 상태 표시
class _SkillRow extends StatelessWidget {
  const _SkillRow({
    required this.spellName,
    required this.rank,
    required this.skill,
    required this.isOnCooldown,
  });

  final String spellName;
  final String rank;
  final Skill? skill;
  final bool isOnCooldown;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 1),
      child: Row(
        children: [
          // 스킬 타입 아이콘
          _buildTypeIcon(),
          const SizedBox(width: 4),
          // 스킬 이름
          Expanded(
            child: Text(
              spellName,
              style: TextStyle(
                fontSize: 11,
                color: isOnCooldown ? Colors.grey : null,
              ),
              overflow: TextOverflow.ellipsis,
            ),
          ),
          // 쿨타임 표시
          if (isOnCooldown)
            const Icon(Icons.hourglass_empty, size: 10, color: Colors.orange),
          const SizedBox(width: 4),
          // 랭크
          Text(
            rank,
            style: const TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
          ),
        ],
      ),
    );
  }

  /// 스킬 타입별 아이콘
  Widget _buildTypeIcon() {
    if (skill == null) {
      return const SizedBox(width: 12);
    }

    final (IconData icon, Color color) = switch (skill!.type) {
      SkillType.attack => (Icons.flash_on, Colors.red),
      SkillType.heal => (Icons.favorite, Colors.green),
      SkillType.buff => (Icons.arrow_upward, Colors.blue),
      SkillType.debuff => (Icons.arrow_downward, Colors.purple),
    };

    return Icon(icon, size: 12, color: color);
  }
}
