import 'dart:async';

import 'package:flutter/material.dart';

import 'package:asciineverdie/l10n/app_localizations.dart';
import 'package:asciineverdie/src/core/engine/arena_service.dart';
import 'package:asciineverdie/src/core/model/arena_match.dart';
import 'package:asciineverdie/src/core/model/combat_event.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
import 'package:asciineverdie/src/shared/animation/race_character_frames.dart';
import 'package:asciineverdie/src/features/arena/widgets/arena_combat_log.dart';
import 'package:asciineverdie/src/features/arena/widgets/arena_hp_bar.dart';
import 'package:asciineverdie/src/features/arena/widgets/arena_result_panel.dart';
import 'package:asciineverdie/src/shared/widgets/ascii_disintegrate_widget.dart';
import 'package:asciineverdie/src/features/game/widgets/ascii_animation_card.dart';
import 'package:asciineverdie/src/features/game/widgets/combat_log.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';

/// 아레나 전투 화면
///
/// ASCII 애니메이션 기반 턴제 전투 표시
/// 레트로 RPG 스타일 HP 바 (세그먼트)
class ArenaBattleScreen extends StatefulWidget {
  const ArenaBattleScreen({
    super.key,
    required this.match,
    required this.onBattleComplete,
  });

  /// 대전 정보
  final ArenaMatch match;

  /// 전투 완료 콜백
  final void Function(ArenaMatchResult) onBattleComplete;

  @override
  State<ArenaBattleScreen> createState() => _ArenaBattleScreenState();
}

class _ArenaBattleScreenState extends State<ArenaBattleScreen>
    with TickerProviderStateMixin {
  final ArenaService _arenaService = ArenaService();

  /// 현재 턴
  int _currentTurn = 0;

  /// 전투 시작 시간 (경과 시간 계산용)
  DateTime? _battleStartTime;

  /// 도전자 HP/MP
  late int _challengerHp;
  late int _challengerHpMax;
  late int _challengerMp;
  late int _challengerMpMax;

  /// 상대 HP/MP
  late int _opponentHp;
  late int _opponentHpMax;
  late int _opponentMp;
  late int _opponentMpMax;

  /// 전투 로그 (CombatLogEntry 사용)
  final List<CombatLogEntry> _battleLog = [];

  /// 전투 시뮬레이션 스트림 구독
  StreamSubscription<ArenaCombatTurn>? _combatSubscription;

  /// 최종 결과
  ArenaMatchResult? _result;

  // HP 변화 애니메이션
  late AnimationController _challengerFlashController;
  late AnimationController _opponentFlashController;
  late Animation<double> _challengerFlashAnimation;
  late Animation<double> _opponentFlashAnimation;

  // 변화량 표시용
  int _challengerHpChange = 0;
  int _opponentHpChange = 0;

  /// 최신 전투 이벤트 (테두리 이펙트용)
  CombatEvent? _latestCombatEvent;

  /// 전투 이벤트 아이콘 타이머 (페이드 아웃용)
  Timer? _eventIconTimer;

  /// 현재 표시 중인 이벤트 아이콘 타입
  CombatEventType? _currentEventIcon;

  /// 현재 표시 중인 스킬 이름
  String? _currentSkillName;

  /// 전투 종료 여부 (결과 패널 표시용)
  bool _isFinished = false;

  @override
  void initState() {
    super.initState();

    // HP/MP 초기화
    _challengerHpMax = widget.match.challenger.finalStats?.hpMax ?? 100;
    _challengerHp = _challengerHpMax;
    _challengerMpMax = widget.match.challenger.finalStats?.mpMax ?? 50;
    _challengerMp = _challengerMpMax;
    _opponentHpMax = widget.match.opponent.finalStats?.hpMax ?? 100;
    _opponentHp = _opponentHpMax;
    _opponentMpMax = widget.match.opponent.finalStats?.mpMax ?? 50;
    _opponentMp = _opponentMpMax;

    // 플래시 애니메이션 초기화
    _challengerFlashController = AnimationController(
      duration: const Duration(milliseconds: 400),
      vsync: this,
    );
    _challengerFlashAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(
        parent: _challengerFlashController,
        curve: Curves.easeOut,
      ),
    );

    _opponentFlashController = AnimationController(
      duration: const Duration(milliseconds: 400),
      vsync: this,
    );
    _opponentFlashAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(parent: _opponentFlashController, curve: Curves.easeOut),
    );

    // 전투 시작 (딜레이 후)
    Future.delayed(const Duration(milliseconds: 500), _startBattle);
  }

  @override
  void dispose() {
    _combatSubscription?.cancel();
    _eventIconTimer?.cancel();
    _challengerFlashController.dispose();
    _opponentFlashController.dispose();
    super.dispose();
  }

  void _startBattle() {
    _battleStartTime = DateTime.now();
    _combatSubscription = _arenaService
        .simulateCombat(widget.match)
        .listen(
          (turn) {
            _processTurn(turn);
          },
          onDone: () {
            _endBattle();
          },
        );
  }

  void _processTurn(ArenaCombatTurn turn) {
    final oldChallengerHp = _challengerHp;
    final oldOpponentHp = _opponentHp;

    setState(() {
      _currentTurn++;
      _challengerHp = turn.challengerHp;
      _opponentHp = turn.opponentHp;
      _challengerMp = turn.challengerMp ?? _challengerMp;
      _opponentMp = turn.opponentMp ?? _opponentMp;

      // 도전자 HP 변화 감지
      if (oldChallengerHp != _challengerHp) {
        _challengerHpChange = _challengerHp - oldChallengerHp;
        _challengerFlashController.forward(from: 0.0);
      }

      // 상대 HP 변화 감지
      if (oldOpponentHp != _opponentHp) {
        _opponentHpChange = _opponentHp - oldOpponentHp;
        _opponentFlashController.forward(from: 0.0);
      }

      // 도전자 스킬 사용 로그
      if (turn.challengerSkillUsed != null) {
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.challenger.characterName} uses '
                '${turn.challengerSkillUsed}!',
            timestamp: DateTime.now(),
            type: CombatLogType.skill,
          ),
        );
      }

      // 도전자 회복 로그
      if (turn.challengerHealAmount != null && turn.challengerHealAmount! > 0) {
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.challenger.characterName} heals '
                '${turn.challengerHealAmount} HP!',
            timestamp: DateTime.now(),
            type: CombatLogType.heal,
          ),
        );
      }

      // 로그 추가 (CombatLogEntry 사용)
      if (turn.challengerDamage != null) {
        final type = turn.isChallengerCritical
            ? CombatLogType.critical
            : CombatLogType.damage;
        final critText = turn.isChallengerCritical ? ' CRITICAL!' : '';
        final skillText = turn.challengerSkillUsed != null ? '' : '';
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.challenger.characterName} deals '
                '${turn.challengerDamage}$critText$skillText',
            timestamp: DateTime.now(),
            type: type,
          ),
        );
      }

      // 상대 회피/블록 이벤트
      if (turn.isOpponentEvaded) {
        _battleLog.add(
          CombatLogEntry(
            message: '${widget.match.opponent.characterName} evaded!',
            timestamp: DateTime.now(),
            type: CombatLogType.evade,
          ),
        );
      }
      if (turn.isOpponentBlocked) {
        _battleLog.add(
          CombatLogEntry(
            message: '${widget.match.opponent.characterName} blocked!',
            timestamp: DateTime.now(),
            type: CombatLogType.block,
          ),
        );
      }

      // 상대 스킬 사용 로그
      if (turn.opponentSkillUsed != null) {
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.opponent.characterName} uses '
                '${turn.opponentSkillUsed}!',
            timestamp: DateTime.now(),
            type: CombatLogType.skill,
          ),
        );
      }

      // 상대 회복 로그
      if (turn.opponentHealAmount != null && turn.opponentHealAmount! > 0) {
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.opponent.characterName} heals '
                '${turn.opponentHealAmount} HP!',
            timestamp: DateTime.now(),
            type: CombatLogType.heal,
          ),
        );
      }

      if (turn.opponentDamage != null) {
        final type = turn.isOpponentCritical
            ? CombatLogType.critical
            : CombatLogType.monsterAttack;
        final critText = turn.isOpponentCritical ? ' CRITICAL!' : '';
        _battleLog.add(
          CombatLogEntry(
            message:
                '${widget.match.opponent.characterName} deals '
                '${turn.opponentDamage}$critText',
            timestamp: DateTime.now(),
            type: type,
          ),
        );
      }

      // 도전자 회피/블록 이벤트
      if (turn.isChallengerEvaded) {
        _battleLog.add(
          CombatLogEntry(
            message: '${widget.match.challenger.characterName} evaded!',
            timestamp: DateTime.now(),
            type: CombatLogType.evade,
          ),
        );
      }
      if (turn.isChallengerBlocked) {
        _battleLog.add(
          CombatLogEntry(
            message: '${widget.match.challenger.characterName} blocked!',
            timestamp: DateTime.now(),
            type: CombatLogType.block,
          ),
        );
      }

      // 전투 이벤트 생성 (테두리 이펙트용)
      _latestCombatEvent = _createCombatEvent(turn);

      // 전투 이벤트 아이콘 표시
      _showEventIcon(turn);
    });
  }

  /// 전투 이벤트 아이콘 표시 (일정 시간 후 사라짐)
  void _showEventIcon(ArenaCombatTurn turn) {
    // 이전 타이머 취소
    _eventIconTimer?.cancel();

    // 스킬 이름 저장
    _currentSkillName = turn.challengerSkillUsed ?? turn.opponentSkillUsed;

    // 이벤트 타입 결정 (우선순위: 스킬 > 크리티컬 > 블록 > 회피 > 일반공격)
    CombatEventType? eventType;
    if (_currentSkillName != null) {
      eventType = CombatEventType.playerSkill;
    } else if (turn.isChallengerCritical || turn.isOpponentCritical) {
      eventType = CombatEventType.playerAttack; // 크리티컬 표시용
    } else if (turn.isChallengerBlocked || turn.isOpponentBlocked) {
      eventType = CombatEventType.playerBlock;
    } else if (turn.isChallengerEvaded || turn.isOpponentEvaded) {
      eventType = CombatEventType.playerEvade;
    } else if (turn.challengerDamage != null || turn.opponentDamage != null) {
      eventType = CombatEventType.playerAttack;
    }

    _currentEventIcon = eventType;

    // 1초 후 아이콘 숨김
    _eventIconTimer = Timer(const Duration(milliseconds: 800), () {
      if (mounted) {
        setState(() {
          _currentEventIcon = null;
          _currentSkillName = null;
        });
      }
    });
  }

  /// ArenaCombatTurn에서 CombatEvent 생성 (테두리 이펙트용)
  CombatEvent? _createCombatEvent(ArenaCombatTurn turn) {
    final timestamp = DateTime.now().millisecondsSinceEpoch;

    // 도전자 스킬 사용 (보라색 테두리)
    if (turn.challengerSkillUsed != null && turn.challengerDamage != null) {
      return CombatEvent.playerSkill(
        timestamp: timestamp,
        skillName: turn.challengerSkillUsed!,
        damage: turn.challengerDamage!,
        targetName: widget.match.opponent.characterName,
        isCritical: turn.isChallengerCritical,
      );
    }

    // 도전자 공격 이벤트 (우선순위: 크리티컬 > 일반 공격)
    if (turn.challengerDamage != null) {
      return CombatEvent.playerAttack(
        timestamp: timestamp,
        damage: turn.challengerDamage!,
        targetName: widget.match.opponent.characterName,
        isCritical: turn.isChallengerCritical,
      );
    }

    // 도전자 회복 이벤트
    if (turn.challengerHealAmount != null && turn.challengerSkillUsed != null) {
      return CombatEvent.playerHeal(
        timestamp: timestamp,
        healAmount: turn.challengerHealAmount!,
        skillName: turn.challengerSkillUsed,
      );
    }

    // 도전자 방어 이벤트 (회피/블록)
    if (turn.isChallengerEvaded) {
      return CombatEvent.playerEvade(
        timestamp: timestamp,
        attackerName: widget.match.opponent.characterName,
      );
    }
    if (turn.isChallengerBlocked) {
      return CombatEvent.playerBlock(
        timestamp: timestamp,
        reducedDamage: turn.opponentDamage ?? 0,
        attackerName: widget.match.opponent.characterName,
      );
    }

    // 상대 공격 이벤트 (몬스터 공격으로 처리)
    if (turn.opponentDamage != null) {
      return CombatEvent.monsterAttack(
        timestamp: timestamp,
        damage: turn.opponentDamage!,
        attackerName: widget.match.opponent.characterName,
      );
    }

    return null;
  }

  void _endBattle() {
    // 시뮬레이션 HP 결과를 기반으로 최종 결과 계산
    _result = _arenaService.createResultFromSimulation(
      match: widget.match,
      challengerHp: _challengerHp,
      opponentHp: _opponentHp,
      turns: _currentTurn,
    );

    // 전투 종료 상태로 전환 (인라인 결과 패널 표시)
    setState(() {
      _isFinished = true;
    });
  }

  /// Continue 버튼 콜백
  void _handleContinue() {
    if (_result != null) {
      widget.onBattleComplete(_result!);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: RetroColors.backgroundOf(context),
      appBar: AppBar(
        title: Text(
          L10n.of(context).arenaBattleTitle,
          style: const TextStyle(fontFamily: 'PressStart2P', fontSize: 15),
        ),
        centerTitle: true,
        backgroundColor: RetroColors.panelBgOf(context),
        automaticallyImplyLeading: false,
      ),
      body: SafeArea(
        child: Column(
          children: [
            // 턴 표시
            _buildTurnIndicator(),
            // HP 바 (레트로 세그먼트 스타일)
            ArenaHpBars(
              challengerName: widget.match.challenger.characterName,
              challengerHp: _challengerHp,
              challengerHpMax: _challengerHpMax,
              challengerFlashAnimation: _challengerFlashAnimation,
              challengerHpChange: _challengerHpChange,
              opponentName: widget.match.opponent.characterName,
              opponentHp: _opponentHp,
              opponentHpMax: _opponentHpMax,
              opponentFlashAnimation: _opponentFlashAnimation,
              opponentHpChange: _opponentHpChange,
            ),
            // 전투 이벤트 아이콘 (HP 바와 애니메이션 사이)
            _buildCombatEventIcons(),
            // ASCII 애니메이션 (전투 중 / 종료 분기)
            _buildBattleArea(),
            // 로그 영역 (남은 공간 채움)
            Expanded(child: _buildBattleLog()),
            // 결과 패널 (전투 종료 시)
            if (_isFinished && _result != null)
              ArenaResultPanel(
                result: _result!,
                turnCount: _currentTurn,
                onContinue: _handleContinue,
                battleLog: _battleLog,
              ),
          ],
        ),
      ),
    );
  }

  /// 방패 장착 여부 확인
  bool _hasShield(HallOfFameEntry entry) {
    final equipment = entry.finalEquipment;
    if (equipment == null) return false;
    return equipment.any((item) => item.slot.name == 'shield');
  }

  /// 전투 영역 (전투 중 / 종료 분기)
  Widget _buildBattleArea() {
    if (_isFinished && _result != null) {
      return _buildFinishedBattleArea();
    }
    return _buildActiveBattleArea();
  }

  /// 활성 전투 영역 (기존 AsciiAnimationCard)
  Widget _buildActiveBattleArea() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8),
      child: SizedBox(
        height: 120,
        child: AsciiAnimationCard(
          taskType: TaskType.kill,
          raceId: widget.match.challenger.raceId,
          shieldName: _hasShield(widget.match.challenger) ? 'shield' : null,
          opponentRaceId: widget.match.opponent.raceId,
          opponentHasShield: _hasShield(widget.match.opponent),
          latestCombatEvent: _latestCombatEvent,
        ),
      ),
    );
  }

  /// 종료된 전투 영역 (승자 유지 + 패자 분해)
  Widget _buildFinishedBattleArea() {
    final isVictory = _result!.isVictory;
    final winnerRaceId = isVictory
        ? widget.match.challenger.raceId
        : widget.match.opponent.raceId;
    final loserRaceId = isVictory
        ? widget.match.opponent.raceId
        : widget.match.challenger.raceId;

    // 패자 캐릭터 프레임 (idle 첫 프레임)
    final loserFrameData =
        RaceCharacterFrames.get(loserRaceId) ??
        RaceCharacterFrames.defaultFrames;
    final loserLines = loserFrameData.idle.first.lines;

    // 승자 캐릭터 프레임 (idle 첫 프레임)
    final winnerFrameData =
        RaceCharacterFrames.get(winnerRaceId) ??
        RaceCharacterFrames.defaultFrames;
    final winnerLines = winnerFrameData.idle.first.lines;

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8),
      child: SizedBox(
        height: 120,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            // 좌측: 도전자 (승자면 유지, 패자면 분해)
            Expanded(
              child: Center(
                child: isVictory
                    ? _buildStaticCharacter(winnerLines, false)
                    : AsciiDisintegrateWidget(
                        characterLines: _mirrorLines(loserLines),
                      ),
              ),
            ),
            // 중앙 VS
            Text(
              'VS',
              style: TextStyle(
                fontFamily: 'PressStart2P',
                fontSize: 14,
                color: RetroColors.goldOf(context).withValues(alpha: 0.5),
              ),
            ),
            // 우측: 상대 (승자면 유지, 패자면 분해)
            Expanded(
              child: Center(
                child: isVictory
                    ? AsciiDisintegrateWidget(characterLines: loserLines)
                    : _buildStaticCharacter(_mirrorLines(winnerLines), false),
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// 정적 ASCII 캐릭터 표시
  Widget _buildStaticCharacter(List<String> lines, bool mirrored) {
    final textColor = RetroColors.textPrimaryOf(context);
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: lines
          .map(
            (line) => Text(
              line,
              style: TextStyle(
                fontFamily: 'JetBrainsMono',
                fontSize: 15,
                color: textColor,
                height: 1.2,
              ),
            ),
          )
          .toList(),
    );
  }

  /// ASCII 문자열 미러링 (좌우 대칭)
  List<String> _mirrorLines(List<String> lines) {
    return lines.map((line) {
      final chars = line.split('');
      return chars.reversed.map(_mirrorChar).join();
    }).toList();
  }

  /// 개별 문자 미러링
  String _mirrorChar(String char) {
    return switch (char) {
      '/' => r'\',
      r'\' => '/',
      '(' => ')',
      ')' => '(',
      '[' => ']',
      ']' => '[',
      '{' => '}',
      '}' => '{',
      '<' => '>',
      '>' => '<',
      'd' => 'b',
      'b' => 'd',
      'q' => 'p',
      'p' => 'q',
      _ => char,
    };
  }

  Widget _buildTurnIndicator() {
    // 경과 시간 계산 (분:초 형식)
    String elapsedTime = '00:00';
    if (_battleStartTime != null) {
      final elapsed = DateTime.now().difference(_battleStartTime!);
      final minutes = elapsed.inMinutes;
      final seconds = elapsed.inSeconds % 60;
      elapsedTime =
          '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
    }

    return Container(
      padding: const EdgeInsets.symmetric(vertical: 8),
      color: RetroColors.panelBgOf(context).withValues(alpha: 0.5),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.timer, color: RetroColors.goldOf(context), size: 16),
          const SizedBox(width: 8),
          Text(
            elapsedTime,
            style: TextStyle(
              fontFamily: 'PressStart2P',
              fontSize: 14,
              color: RetroColors.goldOf(context),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildBattleLog() {
    return Container(
      margin: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: RetroColors.panelBgOf(context),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: RetroColors.borderOf(context)),
      ),
      child: ArenaCombatLog(entries: _battleLog),
    );
  }

  /// 전투 이벤트 아이콘 영역 (HP 바와 애니메이션 사이)
  ///
  /// 메인 게임의 _buildBuffIcons() 스타일을 따름
  /// 스킬 사용, 크리티컬, 블록, 회피 표시
  Widget _buildCombatEventIcons() {
    // 스킬 사용 또는 특수 액션만 표시
    final hasSpecialEvent =
        _currentSkillName != null ||
        _latestCombatEvent?.isCritical == true ||
        _currentEventIcon == CombatEventType.playerBlock ||
        _currentEventIcon == CombatEventType.playerEvade ||
        _currentEventIcon == CombatEventType.playerParry ||
        _currentEventIcon == CombatEventType.playerSkill;

    if (!hasSpecialEvent) {
      return const SizedBox(height: 28);
    }

    // 이벤트 타입에 따른 아이콘/색상 결정
    final (icon, color) = _getEventIconData();

    return AnimatedOpacity(
      opacity: _currentEventIcon != null ? 1.0 : 0.0,
      duration: const Duration(milliseconds: 200),
      child: SizedBox(
        height: 28,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 버프 아이콘 스타일 (CircularProgressIndicator)
            Stack(
              alignment: Alignment.center,
              children: [
                // 원형 진행률 표시 (펄스 효과용)
                SizedBox(
                  width: 24,
                  height: 24,
                  child: CircularProgressIndicator(
                    value: 1.0,
                    strokeWidth: 2,
                    backgroundColor: Colors.grey.shade700,
                    valueColor: AlwaysStoppedAnimation(color),
                  ),
                ),
                // 아이콘
                Icon(icon, size: 12, color: color),
              ],
            ),
            // 스킬 이름 표시
            if (_currentSkillName != null) ...[
              const SizedBox(width: 6),
              Text(
                _currentSkillName!,
                style: TextStyle(
                  fontFamily: 'PressStart2P',
                  fontSize: 12,
                  color: color,
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  /// 이벤트 타입에 따른 아이콘, 색상 반환
  (IconData, Color) _getEventIconData() {
    // 스킬 사용
    if (_currentSkillName != null ||
        _currentEventIcon == CombatEventType.playerSkill) {
      return (Icons.auto_fix_high, Colors.purple);
    }

    // 크리티컬 체크 (latestCombatEvent에서)
    if (_latestCombatEvent?.isCritical == true) {
      return (Icons.flash_on, Colors.yellow.shade600);
    }

    return switch (_currentEventIcon) {
      CombatEventType.playerBlock => (Icons.shield, Colors.blue),
      CombatEventType.playerEvade => (Icons.directions_run, Colors.cyan),
      CombatEventType.playerParry => (Icons.sports_kabaddi, Colors.purple),
      _ => (Icons.trending_up, Colors.lightBlue),
    };
  }
}
