import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

import 'package:asciineverdie/data/game_text_l10n.dart' as game_l10n;
import 'package:asciineverdie/l10n/app_localizations.dart';
import 'package:asciineverdie/src/core/engine/item_service.dart';
import 'package:asciineverdie/src/core/model/arena_match.dart';
import 'package:asciineverdie/src/core/model/equipment_item.dart';
import 'package:asciineverdie/src/core/model/equipment_slot.dart';
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
import 'package:asciineverdie/src/core/model/item_stats.dart';
import 'package:asciineverdie/src/features/game/widgets/combat_log.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';

/// 아레나 결과 패널 (인라인)
///
/// 전투 로그 하단에 표시되는 플로팅 결과 패널
class ArenaResultPanel extends StatefulWidget {
  const ArenaResultPanel({
    super.key,
    required this.result,
    required this.turnCount,
    required this.onContinue,
    this.battleLog,
  });

  /// 대전 결과
  final ArenaMatchResult result;

  /// 총 턴 수
  final int turnCount;

  /// Continue 콜백
  final VoidCallback onContinue;

  /// 배틀 로그 (디버그 모드 저장용)
  final List<CombatLogEntry>? battleLog;

  @override
  State<ArenaResultPanel> createState() => _ArenaResultPanelState();
}

class _ArenaResultPanelState extends State<ArenaResultPanel>
    with SingleTickerProviderStateMixin {
  late AnimationController _slideController;
  late Animation<Offset> _slideAnimation;
  late Animation<double> _fadeAnimation;

  @override
  void initState() {
    super.initState();
    _slideController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );

    _slideAnimation =
        Tween<Offset>(
          begin: const Offset(0, 1), // 아래에서 위로
          end: Offset.zero,
        ).animate(
          CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic),
        );

    _fadeAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(parent: _slideController, curve: Curves.easeOut));

    // 약간 지연 후 애니메이션 시작 (분해 애니메이션과 동기화)
    Future.delayed(const Duration(milliseconds: 800), () {
      if (mounted) {
        _slideController.forward();
      }
    });
  }

  @override
  void dispose() {
    _slideController.dispose();
    super.dispose();
  }

  /// 배틀 로그 JSON 저장 (macOS 디버그 모드 전용)
  Future<void> _saveBattleLog() async {
    if (widget.battleLog == null || widget.battleLog!.isEmpty) return;

    try {
      // macOS: Downloads 폴더에 저장 (사용자가 쉽게 찾을 수 있도록)
      final directory =
          await getDownloadsDirectory() ??
          await getApplicationDocumentsDirectory();
      final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-');
      final challenger = widget.result.match.challenger.characterName;
      final opponent = widget.result.match.opponent.characterName;
      final fileName = 'arena_${challenger}_vs_${opponent}_$timestamp.json';
      final file = File('${directory.path}/$fileName');

      // 전투 통계 계산
      final stats = _calculateBattleStats();

      final jsonData = {
        'match': {
          'challenger': challenger,
          'opponent': opponent,
          'isVictory': widget.result.isVictory,
          'turnCount': widget.turnCount,
          'timestamp': DateTime.now().toIso8601String(),
        },
        'characters': {
          'challenger': _characterToJson(widget.result.match.challenger),
          'opponent': _characterToJson(widget.result.match.opponent),
        },
        'stats': stats,
        'battleLog': widget.battleLog!.map((e) => e.toJson()).toList(),
      };

      await file.writeAsString(
        const JsonEncoder.withIndent('  ').convert(jsonData),
      );

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(
              '${game_l10n.uiSaved}: $fileName',
              style: const TextStyle(fontFamily: 'PressStart2P', fontSize: 11),
            ),
            backgroundColor: RetroColors.mpOf(context),
            duration: const Duration(seconds: 3),
          ),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(
              '${game_l10n.uiError}: $e',
              style: const TextStyle(fontFamily: 'PressStart2P', fontSize: 11),
            ),
            backgroundColor: RetroColors.hpOf(context),
            duration: const Duration(seconds: 3),
          ),
        );
      }
    }
  }

  /// 캐릭터 정보를 JSON으로 변환
  Map<String, dynamic> _characterToJson(HallOfFameEntry entry) {
    return {
      'name': entry.characterName,
      'level': entry.level,
      'race': entry.race,
      'class': entry.klass,
      'combatStats': entry.finalStats?.toJson(),
      'equipment': entry.finalEquipment
          ?.map(
            (EquipmentItem e) => {
              'slot': e.slot.name,
              'name': e.name,
              'level': e.level,
              'rarity': e.rarity.name,
              'stats': e.stats.toJson(),
            },
          )
          .toList(),
      'skills': entry.finalSkills,
    };
  }

  /// 배틀 로그에서 전투 통계 계산
  Map<String, dynamic> _calculateBattleStats() {
    if (widget.battleLog == null || widget.battleLog!.isEmpty) {
      return {};
    }

    int challengerTotalDamage = 0;
    int opponentTotalDamage = 0;
    int challengerTotalHeal = 0;
    int opponentTotalHeal = 0;
    int challengerCriticals = 0;
    int opponentCriticals = 0;
    int challengerBlocks = 0;
    int opponentBlocks = 0;
    int challengerEvades = 0;
    int opponentEvades = 0;
    int challengerSkillsUsed = 0;
    int opponentSkillsUsed = 0;

    final challenger = widget.result.match.challenger.characterName;

    for (final entry in widget.battleLog!) {
      final msg = entry.message;
      final isChallenger = msg.startsWith(challenger);

      switch (entry.type) {
        case CombatLogType.damage:
          final dmg = _extractNumber(msg);
          if (isChallenger) {
            challengerTotalDamage += dmg;
          }
        case CombatLogType.monsterAttack:
          final dmg = _extractNumber(msg);
          opponentTotalDamage += dmg;
        case CombatLogType.critical:
          final dmg = _extractNumber(msg);
          if (isChallenger) {
            challengerTotalDamage += dmg;
            challengerCriticals++;
          } else {
            opponentTotalDamage += dmg;
            opponentCriticals++;
          }
        case CombatLogType.heal:
          final heal = _extractNumber(msg);
          if (isChallenger) {
            challengerTotalHeal += heal;
          } else {
            opponentTotalHeal += heal;
          }
        case CombatLogType.block:
          if (isChallenger) {
            challengerBlocks++;
          } else {
            opponentBlocks++;
          }
        case CombatLogType.evade:
          if (isChallenger) {
            challengerEvades++;
          } else {
            opponentEvades++;
          }
        case CombatLogType.skill:
          if (isChallenger) {
            challengerSkillsUsed++;
          } else {
            opponentSkillsUsed++;
          }
        default:
          break;
      }
    }

    return {
      'challenger': {
        'totalDamage': challengerTotalDamage,
        'totalHeal': challengerTotalHeal,
        'criticals': challengerCriticals,
        'blocks': challengerBlocks,
        'evades': challengerEvades,
        'skillsUsed': challengerSkillsUsed,
      },
      'opponent': {
        'totalDamage': opponentTotalDamage,
        'totalHeal': opponentTotalHeal,
        'criticals': opponentCriticals,
        'blocks': opponentBlocks,
        'evades': opponentEvades,
        'skillsUsed': opponentSkillsUsed,
      },
    };
  }

  /// 메시지에서 숫자 추출
  int _extractNumber(String msg) {
    final match = RegExp(r'(\d+)').firstMatch(msg);
    return match != null ? int.tryParse(match.group(1)!) ?? 0 : 0;
  }

  @override
  Widget build(BuildContext context) {
    final isVictory = widget.result.isVictory;
    final resultColor = isVictory ? Colors.amber : Colors.red.shade400;
    final panelColor = isVictory
        ? RetroColors.goldOf(context).withValues(alpha: 0.15)
        : Colors.red.withValues(alpha: 0.1);
    final borderColor = isVictory
        ? RetroColors.goldOf(context)
        : Colors.red.shade400;

    return SlideTransition(
      position: _slideAnimation,
      child: FadeTransition(
        opacity: _fadeAnimation,
        child: Container(
          margin: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            color: RetroColors.panelBgOf(context),
            borderRadius: BorderRadius.circular(8),
            border: Border.all(color: borderColor, width: 2),
            boxShadow: [
              BoxShadow(
                color: borderColor.withValues(alpha: 0.3),
                blurRadius: 8,
                spreadRadius: 1,
              ),
            ],
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // 타이틀 배너
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(vertical: 8),
                decoration: BoxDecoration(
                  color: panelColor,
                  borderRadius: const BorderRadius.vertical(
                    top: Radius.circular(6),
                  ),
                ),
                child: _buildTitle(context, isVictory, resultColor),
              ),
              // 내용
              Padding(
                padding: const EdgeInsets.all(12),
                child: Column(
                  children: [
                    // 전투 요약 (턴 수)
                    _buildBattleSummary(context),
                    const SizedBox(height: 12),
                    // 장비 교환
                    _buildExchangeSection(context),
                    const SizedBox(height: 12),
                    // 배틀로그 저장 버튼 (macOS 디버그 모드 전용)
                    if (kDebugMode &&
                        Platform.isMacOS &&
                        widget.battleLog != null) ...[
                      _buildSaveLogButton(context),
                      const SizedBox(height: 8),
                    ],
                    // Continue 버튼
                    _buildContinueButton(context, resultColor),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildTitle(BuildContext context, bool isVictory, Color color) {
    final l10n = L10n.of(context);
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(
          isVictory ? Icons.emoji_events : Icons.sentiment_very_dissatisfied,
          color: color,
          size: 20,
        ),
        const SizedBox(width: 8),
        Text(
          isVictory ? l10n.arenaVictory : l10n.arenaDefeat,
          style: TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 14,
            color: color,
          ),
        ),
        const SizedBox(width: 8),
        Icon(
          isVictory ? Icons.emoji_events : Icons.sentiment_very_dissatisfied,
          color: color,
          size: 20,
        ),
      ],
    );
  }

  Widget _buildBattleSummary(BuildContext context) {
    final l10n = L10n.of(context);
    final winner = widget.result.isVictory
        ? widget.result.match.challenger.characterName
        : widget.result.match.opponent.characterName;
    final loser = widget.result.isVictory
        ? widget.result.match.opponent.characterName
        : widget.result.match.challenger.characterName;
    final summaryText = l10n.arenaDefeatedIn(winner, loser, widget.turnCount);

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8),
      child: Text(
        summaryText,
        style: TextStyle(
          fontFamily: 'PressStart2P',
          fontSize: 11,
          color: RetroColors.textSecondaryOf(context),
        ),
        textAlign: TextAlign.center,
      ),
    );
  }

  Widget _buildExchangeSection(BuildContext context) {
    final isVictory = widget.result.isVictory;

    // 승패에 따라 교환 슬롯 결정
    // 승리: 도전자가 선택한 슬롯(상대에게서 약탈)
    // 패배: 상대가 선택한 슬롯(도전자에게서 약탈당함)
    final slot = isVictory
        ? widget.result.match.challengerBettingSlot
        : widget.result.match.opponentBettingSlot;

    // 도전자의 교환 결과
    final oldItem = _findItem(
      widget.result.match.challenger.finalEquipment,
      slot,
    );
    final newItem = _findItem(
      widget.result.updatedChallenger.finalEquipment,
      slot,
    );

    final oldScore = oldItem != null
        ? ItemService.calculateEquipmentScore(oldItem)
        : 0;
    final newScore = newItem != null
        ? ItemService.calculateEquipmentScore(newItem)
        : 0;
    final scoreDiff = newScore - oldScore;

    return Container(
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: isVictory
            ? Colors.green.withValues(alpha: 0.1)
            : Colors.red.withValues(alpha: 0.1),
        borderRadius: BorderRadius.circular(6),
        border: Border.all(
          color: isVictory
              ? Colors.green.withValues(alpha: 0.3)
              : Colors.red.withValues(alpha: 0.3),
        ),
      ),
      child: Column(
        children: [
          // 교환 타이틀
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.swap_horiz,
                color: RetroColors.goldOf(context),
                size: 14,
              ),
              const SizedBox(width: 4),
              Text(
                L10n.of(context).arenaEquipmentExchange,
                style: TextStyle(
                  fontFamily: 'PressStart2P',
                  fontSize: 12,
                  color: RetroColors.goldOf(context),
                ),
              ),
            ],
          ),
          const SizedBox(height: 8),
          // 슬롯
          Text(
            _getSlotLabel(slot),
            style: TextStyle(
              fontFamily: 'PressStart2P',
              fontSize: 12,
              color: RetroColors.textMutedOf(context),
            ),
          ),
          const SizedBox(height: 8),
          // 교환 내용
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // 이전 아이템
              _buildItemBadge(context, oldItem, oldScore),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: Icon(
                  Icons.arrow_forward,
                  size: 14,
                  color: RetroColors.textMutedOf(context),
                ),
              ),
              // 새 아이템
              _buildItemBadge(context, newItem, newScore),
              const SizedBox(width: 8),
              // 점수 변화
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                decoration: BoxDecoration(
                  color: scoreDiff >= 0
                      ? Colors.green.withValues(alpha: 0.2)
                      : Colors.red.withValues(alpha: 0.2),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(
                      scoreDiff >= 0
                          ? Icons.arrow_upward
                          : Icons.arrow_downward,
                      size: 10,
                      color: scoreDiff >= 0 ? Colors.green : Colors.red,
                    ),
                    Text(
                      '${scoreDiff >= 0 ? '+' : ''}$scoreDiff',
                      style: TextStyle(
                        fontFamily: 'PressStart2P',
                        fontSize: 11,
                        color: scoreDiff >= 0 ? Colors.green : Colors.red,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildItemBadge(BuildContext context, EquipmentItem? item, int score) {
    if (item == null || item.isEmpty) {
      return Container(
        padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
        decoration: BoxDecoration(
          color: Colors.grey.withValues(alpha: 0.2),
          borderRadius: BorderRadius.circular(4),
          border: Border.all(color: Colors.grey.withValues(alpha: 0.3)),
        ),
        child: Text(
          '(empty)',
          style: TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 11,
            color: RetroColors.textMutedOf(context),
          ),
        ),
      );
    }

    final rarityColor = _getRarityColor(item.rarity);

    return Container(
      constraints: const BoxConstraints(maxWidth: 80),
      padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
      decoration: BoxDecoration(
        color: rarityColor.withValues(alpha: 0.15),
        borderRadius: BorderRadius.circular(4),
        border: Border.all(color: rarityColor.withValues(alpha: 0.5)),
      ),
      child: Column(
        children: [
          Text(
            item.name,
            style: TextStyle(
              fontFamily: 'PressStart2P',
              fontSize: 12,
              color: rarityColor,
            ),
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
          Text(
            '$score pt',
            style: TextStyle(
              fontFamily: 'PressStart2P',
              fontSize: 12,
              color: RetroColors.textMutedOf(context),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildContinueButton(BuildContext context, Color color) {
    return SizedBox(
      width: double.infinity,
      child: FilledButton(
        onPressed: widget.onContinue,
        style: FilledButton.styleFrom(
          backgroundColor: color,
          padding: const EdgeInsets.symmetric(vertical: 10),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
        ),
        child: Text(
          game_l10n.buttonConfirm,
          style: const TextStyle(
            fontFamily: 'PressStart2P',
            fontSize: 13,
            color: Colors.black,
          ),
        ),
      ),
    );
  }

  /// 배틀로그 저장 버튼 (macOS 디버그 모드 전용)
  Widget _buildSaveLogButton(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: OutlinedButton.icon(
        onPressed: _saveBattleLog,
        icon: const Icon(Icons.save_alt, size: 14),
        label: Text(
          game_l10n.uiSaveBattleLog,
          style: const TextStyle(fontFamily: 'PressStart2P', fontSize: 11),
        ),
        style: OutlinedButton.styleFrom(
          foregroundColor: RetroColors.mpOf(context),
          side: BorderSide(color: RetroColors.mpOf(context)),
          padding: const EdgeInsets.symmetric(vertical: 8),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
        ),
      ),
    );
  }

  EquipmentItem? _findItem(List<EquipmentItem>? equipment, EquipmentSlot slot) {
    if (equipment == null) return null;
    for (final item in equipment) {
      if (item.slot == slot) return item;
    }
    return null;
  }

  String _getSlotLabel(EquipmentSlot slot) {
    return switch (slot) {
      EquipmentSlot.weapon => game_l10n.slotWeapon,
      EquipmentSlot.shield => game_l10n.slotShield,
      EquipmentSlot.helm => game_l10n.slotHelm,
      EquipmentSlot.hauberk => game_l10n.slotHauberk,
      EquipmentSlot.brassairts => game_l10n.slotBrassairts,
      EquipmentSlot.vambraces => game_l10n.slotVambraces,
      EquipmentSlot.gauntlets => game_l10n.slotGauntlets,
      EquipmentSlot.gambeson => game_l10n.slotGambeson,
      EquipmentSlot.cuisses => game_l10n.slotCuisses,
      EquipmentSlot.greaves => game_l10n.slotGreaves,
      EquipmentSlot.sollerets => game_l10n.slotSollerets,
    };
  }

  Color _getRarityColor(ItemRarity rarity) {
    return switch (rarity) {
      ItemRarity.common => Colors.grey.shade600,
      ItemRarity.uncommon => Colors.green.shade600,
      ItemRarity.rare => Colors.blue.shade600,
      ItemRarity.epic => Colors.purple.shade600,
      ItemRarity.legendary => Colors.orange.shade700,
    };
  }
}
