import 'package:flutter/material.dart';

import 'package:asciineverdie/data/game_text_l10n.dart' as l10n;
import 'package:asciineverdie/src/core/animation/ascii_animation_type.dart';
import 'package:asciineverdie/src/core/animation/monster_size.dart';
import 'package:asciineverdie/src/core/model/combat_event.dart';
import 'package:asciineverdie/src/core/model/combat_state.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/item_stats.dart';
import 'package:asciineverdie/src/core/model/monster_grade.dart';
import 'package:asciineverdie/src/features/game/widgets/ascii_animation_card.dart';

/// 모바일용 확장 애니메이션 패널
///
/// 캐로셀 레이아웃에서 상단 영역에 표시되는 통합 패널:
/// - ASCII 애니메이션 (기존 높이 유지)
/// - 플레이어 HP/MP 컴팩트 바 (플로팅 텍스트 포함)
/// - 활성 버프 아이콘 (최대 3개)
/// - 몬스터 HP 바 (전투 중)
class EnhancedAnimationPanel extends StatefulWidget {
  const EnhancedAnimationPanel({
    super.key,
    required this.progress,
    required this.stats,
    required this.skillSystem,
    required this.speedMultiplier,
    required this.onSpeedCycle,
    required this.isPaused,
    required this.onPauseToggle,
    this.specialAnimation,
    this.weaponName,
    this.shieldName,
    this.characterLevel,
    this.monsterLevel,
    this.monsterGrade,
    this.monsterSize,
    this.latestCombatEvent,
    this.raceId,
    this.weaponRarity,
    this.autoReviveEndMs,
    this.speedBoostEndMs,
    this.isPaidUser = false,
    this.onSpeedBoostActivate,
  });

  final ProgressState progress;
  final Stats stats;
  final SkillSystemState skillSystem;
  final int speedMultiplier;
  final VoidCallback onSpeedCycle;
  final bool isPaused;
  final VoidCallback onPauseToggle;
  final AsciiAnimationType? specialAnimation;
  final String? weaponName;
  final String? shieldName;
  final int? characterLevel;
  final int? monsterLevel;

  /// 몬스터 등급 (Normal/Elite/Boss) - UI 색상/접두사 표시용
  final MonsterGrade? monsterGrade;

  /// 몬스터 사이즈 (애니메이션 크기 결정용, Act 기반)
  final MonsterSize? monsterSize;
  final CombatEvent? latestCombatEvent;

  /// 종족 ID (Phase 4: 종족별 캐릭터 애니메이션)
  final String? raceId;

  /// 무기 희귀도 (Phase 9: 무기 등급별 이펙트 색상)
  final ItemRarity? weaponRarity;

  /// 자동부활 버프 종료 시점 (elapsedMs 기준, null이면 비활성)
  final int? autoReviveEndMs;

  /// 5배속 버프 종료 시점 (elapsedMs 기준, null이면 비활성)
  final int? speedBoostEndMs;

  /// 유료 유저 여부 (5배속 항상 활성)
  final bool isPaidUser;

  /// 5배속 버프 활성화 콜백 (광고 시청)
  final VoidCallback? onSpeedBoostActivate;

  @override
  State<EnhancedAnimationPanel> createState() => _EnhancedAnimationPanelState();
}

class _EnhancedAnimationPanelState extends State<EnhancedAnimationPanel>
    with TickerProviderStateMixin {
  // HP/MP 변화 애니메이션
  late AnimationController _hpFlashController;
  late AnimationController _mpFlashController;
  late AnimationController _monsterFlashController;
  late Animation<double> _hpFlashAnimation;
  late Animation<double> _mpFlashAnimation;
  late Animation<double> _monsterFlashAnimation;

  int _hpChange = 0;
  int _mpChange = 0;
  int _monsterHpChange = 0;

  // 이전 값 추적
  int _lastHp = 0;
  int _lastMp = 0;
  int _lastMonsterHp = 0;

  // 몬스터 사망 상태 추적
  bool _monsterDied = false;
  bool _wasInCombat = false;

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

    _hpFlashController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );
    _mpFlashController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );
    _monsterFlashController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );

    _hpFlashAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(parent: _hpFlashController, curve: Curves.easeOut),
    );
    _mpFlashAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(parent: _mpFlashController, curve: Curves.easeOut),
    );
    _monsterFlashAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(parent: _monsterFlashController, curve: Curves.easeOut),
    );

    // 초기값 설정
    _lastHp = _currentHp;
    _lastMp = _currentMp;
    _lastMonsterHp = _currentMonsterHp ?? 0;
  }

  @override
  void didUpdateWidget(EnhancedAnimationPanel oldWidget) {
    super.didUpdateWidget(oldWidget);

    // HP 변화 감지
    final newHp = _currentHp;
    if (newHp != _lastHp) {
      _hpChange = newHp - _lastHp;
      _hpFlashController.forward(from: 0.0);
      _lastHp = newHp;
    }

    // MP 변화 감지
    final newMp = _currentMp;
    if (newMp != _lastMp) {
      _mpChange = newMp - _lastMp;
      _mpFlashController.forward(from: 0.0);
      _lastMp = newMp;
    }

    // 몬스터 HP 변화 감지
    final newMonsterHp = _currentMonsterHp;
    if (newMonsterHp != null && newMonsterHp != _lastMonsterHp) {
      _monsterHpChange = newMonsterHp - _lastMonsterHp;
      _monsterFlashController.forward(from: 0.0);
      _lastMonsterHp = newMonsterHp;
    } else if (newMonsterHp == null) {
      _lastMonsterHp = 0;
    }

    // 몬스터 사망 감지: 전투 중 → 비전투 전환 시 몬스터 사망
    final combat = widget.progress.currentCombat;
    final isNowInCombat = combat != null && combat.isActive;
    if (_wasInCombat && !isNowInCombat) {
      // 전투가 끝났고, 태스크가 여전히 kill이면 몬스터 사망 (플레이어 승리)
      if (widget.progress.currentTask.type == TaskType.kill) {
        setState(() {
          _monsterDied = true;
        });
        // 잠시 후 리셋 (애니메이션 완료 후)
        Future.delayed(const Duration(milliseconds: 900), () {
          if (mounted) {
            setState(() {
              _monsterDied = false;
            });
          }
        });
      }
    }
    _wasInCombat = isNowInCombat;
  }

  int get _currentHp =>
      widget.progress.currentCombat?.playerStats.hpCurrent ?? widget.stats.hp;
  int get _currentHpMax =>
      widget.progress.currentCombat?.playerStats.hpMax ?? widget.stats.hpMax;
  int get _currentMp =>
      widget.progress.currentCombat?.playerStats.mpCurrent ?? widget.stats.mp;
  int get _currentMpMax =>
      widget.progress.currentCombat?.playerStats.mpMax ?? widget.stats.mpMax;
  int? get _currentMonsterHp =>
      widget.progress.currentCombat?.monsterStats.hpCurrent;
  int? get _currentMonsterHpMax =>
      widget.progress.currentCombat?.monsterStats.hpMax;

  /// 자동부활 버프 남은 시간 (ms)
  int get _autoReviveRemainingMs {
    final endMs = widget.autoReviveEndMs;
    if (endMs == null) return 0;
    final remaining = endMs - widget.skillSystem.elapsedMs;
    return remaining > 0 ? remaining : 0;
  }

  /// 5배속 버프 남은 시간 (ms)
  int get _speedBoostRemainingMs {
    final endMs = widget.speedBoostEndMs;
    if (endMs == null) return 0;
    final remaining = endMs - widget.skillSystem.elapsedMs;
    return remaining > 0 ? remaining : 0;
  }

  @override
  void dispose() {
    _hpFlashController.dispose();
    _mpFlashController.dispose();
    _monsterFlashController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final combat = widget.progress.currentCombat;
    final isInCombat = combat != null && combat.isActive;
    // 몬스터 HP는 전투 중이면서 kill 태스크일 때만 표시
    // (전투 승리 후 타운 방문 시 HP UI 잔존 버그 방지)
    final isKillTask = widget.progress.currentTask.type == TaskType.kill;
    final shouldShowMonsterHp = isInCombat && isKillTask;

    return Container(
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surfaceContainerHighest,
        border: Border(
          bottom: BorderSide(color: Theme.of(context).dividerColor),
        ),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          // ASCII 애니메이션 (기존 높이 120 유지) + 버프 오버레이
          SizedBox(
            height: 120,
            child: Stack(
              children: [
                // ASCII 애니메이션
                AsciiAnimationCard(
                  taskType: widget.progress.currentTask.type,
                  monsterBaseName: widget.progress.currentTask.monsterBaseName,
                  specialAnimation: widget.specialAnimation,
                  weaponName: widget.weaponName,
                  shieldName: widget.shieldName,
                  characterLevel: widget.characterLevel,
                  monsterLevel: widget.monsterLevel,
                  monsterGrade: widget.monsterGrade,
                  monsterSize: widget.monsterSize,
                  isPaused: widget.isPaused,
                  isInCombat: isInCombat,
                  monsterDied: _monsterDied,
                  latestCombatEvent: widget.latestCombatEvent,
                  raceId: widget.raceId,
                  weaponRarity: widget.weaponRarity,
                ),
                // 좌상단: 자동부활 버프
                if (_autoReviveRemainingMs > 0)
                  Positioned(
                    left: 4,
                    top: 4,
                    child: _buildBuffChip(
                      icon: '↺',
                      remainingMs: _autoReviveRemainingMs,
                      color: Colors.green,
                    ),
                  ),
                // 우상단: 5배속 버프
                if (_speedBoostRemainingMs > 0 || widget.isPaidUser)
                  Positioned(
                    right: 4,
                    top: 4,
                    child: _buildBuffChip(
                      icon: '⚡',
                      label: '5x',
                      remainingMs: widget.isPaidUser ? -1 : _speedBoostRemainingMs,
                      color: Colors.orange,
                      isPermanent: widget.isPaidUser,
                    ),
                  ),
              ],
            ),
          ),

          const SizedBox(height: 8),

          // 상태 바 영역: HP/MP (40%) + 컨트롤 (20%) + 몬스터 HP (40%)
          SizedBox(
            height: 48,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // 좌측: HP/MP 바 (40%)
                Expanded(
                  flex: 2,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      Expanded(child: _buildCompactHpBar()),
                      const SizedBox(height: 4),
                      Expanded(child: _buildCompactMpBar()),
                    ],
                  ),
                ),

                // 중앙: 컨트롤 버튼 (20%)
                Expanded(
                  flex: 1,
                  child: _buildControlButtons(),
                ),

                // 우측: 몬스터 HP (전투 중) 또는 빈 공간 (40%)
                Expanded(
                  flex: 2,
                  child: switch ((shouldShowMonsterHp, combat)) {
                    (true, final c?) => _buildMonsterHpBar(c),
                    _ => const SizedBox.shrink(),
                  },
                ),
              ],
            ),
          ),

          const SizedBox(height: 6),

          // 하단: 태스크 프로그레스 바 + 캡션
          _buildTaskProgress(),
        ],
      ),
    );
  }

  /// 컴팩트 HP 바 (숫자 오버레이)
  Widget _buildCompactHpBar() {
    final ratio = _currentHpMax > 0 ? _currentHp / _currentHpMax : 0.0;
    final isLow = ratio < 0.2 && ratio > 0;

    return AnimatedBuilder(
      animation: _hpFlashAnimation,
      builder: (context, child) {
        return Stack(
          clipBehavior: Clip.none,
          children: [
            // HP 바
            Container(
              decoration: BoxDecoration(
                color: isLow
                    ? Colors.red.withValues(alpha: 0.2)
                    : Colors.grey.shade800,
                borderRadius: BorderRadius.circular(3),
              ),
              child: Row(
                children: [
                  // 라벨
                  Container(
                    width: 32,
                    alignment: Alignment.center,
                    child: Text(
                      l10n.statHp,
                      style: const TextStyle(
                        fontSize: 11,
                        fontWeight: FontWeight.bold,
                        color: Colors.white70,
                      ),
                    ),
                  ),
                  // 프로그레스 바 + 숫자 오버레이
                  Expanded(
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        // 프로그레스 바
                        ClipRRect(
                          borderRadius: const BorderRadius.horizontal(
                            right: Radius.circular(3),
                          ),
                          child: SizedBox.expand(
                            child: LinearProgressIndicator(
                              value: ratio.clamp(0.0, 1.0),
                              backgroundColor: Colors.red.withValues(alpha: 0.2),
                              valueColor: AlwaysStoppedAnimation(
                                isLow ? Colors.red : Colors.red.shade600,
                              ),
                            ),
                          ),
                        ),
                        // 숫자 오버레이 (바 중앙)
                        Text(
                          '$_currentHp/$_currentHpMax',
                          style: TextStyle(
                            fontSize: 11,
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                            shadows: [
                              Shadow(
                                color: Colors.black.withValues(alpha: 0.9),
                                blurRadius: 2,
                              ),
                              const Shadow(color: Colors.black, blurRadius: 4),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),

            // 플로팅 변화량
            if (_hpChange != 0 && _hpFlashAnimation.value > 0.05)
              Positioned(
                right: 20,
                top: -8,
                child: Transform.translate(
                  offset: Offset(0, -10 * (1 - _hpFlashAnimation.value)),
                  child: Opacity(
                    opacity: _hpFlashAnimation.value,
                    child: Text(
                      _hpChange > 0 ? '+$_hpChange' : '$_hpChange',
                      style: TextStyle(
                        fontSize: 13,
                        fontWeight: FontWeight.bold,
                        color: _hpChange < 0 ? Colors.red : Colors.green,
                        shadows: const [
                          Shadow(color: Colors.black, blurRadius: 3),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
          ],
        );
      },
    );
  }

  /// 컴팩트 MP 바 (숫자 오버레이)
  Widget _buildCompactMpBar() {
    final ratio = _currentMpMax > 0 ? _currentMp / _currentMpMax : 0.0;

    return AnimatedBuilder(
      animation: _mpFlashAnimation,
      builder: (context, child) {
        return Stack(
          clipBehavior: Clip.none,
          children: [
            Container(
              decoration: BoxDecoration(
                color: Colors.grey.shade800,
                borderRadius: BorderRadius.circular(3),
              ),
              child: Row(
                children: [
                  Container(
                    width: 32,
                    alignment: Alignment.center,
                    child: Text(
                      l10n.statMp,
                      style: const TextStyle(
                        fontSize: 11,
                        fontWeight: FontWeight.bold,
                        color: Colors.white70,
                      ),
                    ),
                  ),
                  // 프로그레스 바 + 숫자 오버레이
                  Expanded(
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        // 프로그레스 바
                        ClipRRect(
                          borderRadius: const BorderRadius.horizontal(
                            right: Radius.circular(3),
                          ),
                          child: SizedBox.expand(
                            child: LinearProgressIndicator(
                              value: ratio.clamp(0.0, 1.0),
                              backgroundColor: Colors.blue.withValues(alpha: 0.2),
                              valueColor: AlwaysStoppedAnimation(
                                Colors.blue.shade600,
                              ),
                            ),
                          ),
                        ),
                        // 숫자 오버레이 (바 중앙)
                        Text(
                          '$_currentMp/$_currentMpMax',
                          style: TextStyle(
                            fontSize: 11,
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                            shadows: [
                              Shadow(
                                color: Colors.black.withValues(alpha: 0.9),
                                blurRadius: 2,
                              ),
                              const Shadow(color: Colors.black, blurRadius: 4),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),

            if (_mpChange != 0 && _mpFlashAnimation.value > 0.05)
              Positioned(
                right: 20,
                top: -8,
                child: Transform.translate(
                  offset: Offset(0, -10 * (1 - _mpFlashAnimation.value)),
                  child: Opacity(
                    opacity: _mpFlashAnimation.value,
                    child: Text(
                      _mpChange > 0 ? '+$_mpChange' : '$_mpChange',
                      style: TextStyle(
                        fontSize: 13,
                        fontWeight: FontWeight.bold,
                        color: _mpChange < 0 ? Colors.orange : Colors.cyan,
                        shadows: const [
                          Shadow(color: Colors.black, blurRadius: 3),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
          ],
        );
      },
    );
  }

  /// 몬스터 HP 바 (전투 중)
  /// - HP바 중앙에 HP% 오버레이
  /// - 하단에 레벨.이름 표시
  Widget _buildMonsterHpBar(CombatState combat) {
    final max = _currentMonsterHpMax ?? 1;
    final current = _currentMonsterHp ?? 0;
    final ratio = max > 0 ? current / max : 0.0;
    final monsterName = combat.monsterStats.name;
    final monsterLevel = widget.monsterLevel ?? combat.monsterStats.level;

    return AnimatedBuilder(
      animation: _monsterFlashAnimation,
      builder: (context, child) {
        return Stack(
          clipBehavior: Clip.none,
          children: [
            Container(
              decoration: BoxDecoration(
                color: Colors.orange.withValues(alpha: 0.1),
                borderRadius: BorderRadius.circular(4),
                border: Border.all(color: Colors.orange.withValues(alpha: 0.3)),
              ),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // HP 바 (HP% 중앙 오버레이)
                  Expanded(
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(4, 4, 4, 2),
                      child: Stack(
                        alignment: Alignment.center,
                        children: [
                          // HP 바
                          ClipRRect(
                            borderRadius: BorderRadius.circular(2),
                            child: SizedBox.expand(
                              child: LinearProgressIndicator(
                                value: ratio.clamp(0.0, 1.0),
                                backgroundColor: Colors.orange.withValues(
                                  alpha: 0.2,
                                ),
                                valueColor: const AlwaysStoppedAnimation(
                                  Colors.orange,
                                ),
                              ),
                            ),
                          ),
                          // HP% 중앙 오버레이
                          Text(
                            '${(ratio * 100).toInt()}%',
                            style: TextStyle(
                              fontSize: 12,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                              shadows: [
                                Shadow(
                                  color: Colors.black.withValues(alpha: 0.8),
                                  blurRadius: 2,
                                ),
                                const Shadow(color: Colors.black, blurRadius: 4),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                  // 레벨.이름 표시
                  Padding(
                    padding: const EdgeInsets.fromLTRB(4, 0, 4, 4),
                    child: Text(
                      'Lv.$monsterLevel $monsterName',
                      style: const TextStyle(
                        fontSize: 11,
                        color: Colors.orange,
                        fontWeight: FontWeight.bold,
                      ),
                      overflow: TextOverflow.ellipsis,
                      maxLines: 1,
                    ),
                  ),
                ],
              ),
            ),

            // 플로팅 데미지
            if (_monsterHpChange != 0 && _monsterFlashAnimation.value > 0.05)
              Positioned(
                right: 10,
                top: -10,
                child: Transform.translate(
                  offset: Offset(0, -10 * (1 - _monsterFlashAnimation.value)),
                  child: Opacity(
                    opacity: _monsterFlashAnimation.value,
                    child: Text(
                      _monsterHpChange > 0
                          ? '+$_monsterHpChange'
                          : '$_monsterHpChange',
                      style: TextStyle(
                        fontSize: 17,
                        fontWeight: FontWeight.bold,
                        color: _monsterHpChange < 0
                            ? Colors.yellow
                            : Colors.green,
                        shadows: const [
                          Shadow(color: Colors.black, blurRadius: 3),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
          ],
        );
      },
    );
  }

  /// 컨트롤 버튼 (중앙 영역)
  Widget _buildControlButtons() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // 상단: 속도 버튼 (1x ↔ 2x)
        _buildCompactSpeedButton(),
        const SizedBox(height: 2),
        // 하단: 5x 광고 버튼 (2x일 때만 표시)
        _buildAdSpeedButton(),
      ],
    );
  }

  /// 컴팩트 속도 버튼 (1x ↔ 2x 사이클)
  Widget _buildCompactSpeedButton() {
    final isSpeedBoostActive = _speedBoostRemainingMs > 0 || widget.isPaidUser;

    return SizedBox(
      width: 32,
      height: 22,
      child: OutlinedButton(
        onPressed: widget.onSpeedCycle,
        style: OutlinedButton.styleFrom(
          padding: EdgeInsets.zero,
          visualDensity: VisualDensity.compact,
          side: BorderSide(
            color: isSpeedBoostActive
                ? Colors.orange
                : widget.speedMultiplier > 1
                    ? Theme.of(context).colorScheme.primary
                    : Theme.of(context).colorScheme.outline.withValues(alpha: 0.5),
          ),
        ),
        child: Text(
          isSpeedBoostActive ? '5x' : '${widget.speedMultiplier}x',
          style: TextStyle(
            fontSize: 10,
            fontWeight: FontWeight.bold,
            color: isSpeedBoostActive
                ? Colors.orange
                : widget.speedMultiplier > 1
                    ? Theme.of(context).colorScheme.primary
                    : null,
          ),
        ),
      ),
    );
  }

  /// 5x 광고 버튼 (2x일 때만 표시)
  Widget _buildAdSpeedButton() {
    final isSpeedBoostActive = _speedBoostRemainingMs > 0 || widget.isPaidUser;
    // 2x이고 5배속 버프 비활성이고 무료유저일 때만 표시
    final showAdButton =
        widget.speedMultiplier == 2 && !isSpeedBoostActive && !widget.isPaidUser;

    if (!showAdButton) {
      return const SizedBox(height: 22);
    }

    return SizedBox(
      height: 22,
      child: OutlinedButton(
        onPressed: widget.onSpeedBoostActivate,
        style: OutlinedButton.styleFrom(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          visualDensity: VisualDensity.compact,
          side: const BorderSide(color: Colors.orange),
        ),
        child: const Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('▶', style: TextStyle(fontSize: 8, color: Colors.orange)),
            SizedBox(width: 2),
            Text(
              '5x',
              style: TextStyle(
                fontSize: 10,
                fontWeight: FontWeight.bold,
                color: Colors.orange,
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// 현재 상태에 맞는 메시지 반환
  ///
  /// 특수 애니메이션(부활 등) 중에는 해당 메시지 표시
  String _getStatusMessage() {
    // 부활 애니메이션 중에는 부활 메시지 표시
    if (widget.specialAnimation == AsciiAnimationType.resurrection) {
      return l10n.animationResurrecting;
    }

    // 기본: 현재 태스크 캡션
    return widget.progress.currentTask.caption;
  }

  /// 태스크 프로그레스 바
  Widget _buildTaskProgress() {
    final task = widget.progress.task;
    final progressValue = task.max > 0
        ? (task.position / task.max).clamp(0.0, 1.0)
        : 0.0;

    // 몬스터 등급에 따른 접두사와 색상
    final grade = widget.monsterGrade;
    final isKillTask = widget.progress.currentTask.type == TaskType.kill;
    final gradePrefix = (isKillTask && grade != null)
        ? grade.displayPrefix
        : '';
    final gradeColor = (isKillTask && grade != null)
        ? grade.displayColor
        : null;

    return Column(
      children: [
        // 캡션 (등급에 따른 접두사 및 색상)
        Text.rich(
          TextSpan(
            children: [
              if (gradePrefix.isNotEmpty)
                TextSpan(
                  text: gradePrefix,
                  style: TextStyle(
                    color: gradeColor,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              TextSpan(
                text: _getStatusMessage(),
                style: gradeColor != null ? TextStyle(color: gradeColor) : null,
              ),
            ],
          ),
          style: Theme.of(context).textTheme.bodySmall,
          textAlign: TextAlign.center,
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ),
        const SizedBox(height: 4),
        // 프로그레스 바
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          child: LinearProgressIndicator(
            value: progressValue,
            backgroundColor: Theme.of(
              context,
            ).colorScheme.primary.withValues(alpha: 0.2),
            valueColor: AlwaysStoppedAnimation<Color>(
              Theme.of(context).colorScheme.primary,
            ),
            minHeight: 10,
          ),
        ),
      ],
    );
  }

  /// 버프 칩 위젯 (좌상단/우상단 오버레이용)
  Widget _buildBuffChip({
    required String icon,
    required int remainingMs,
    required Color color,
    String? label,
    bool isPermanent = false,
  }) {
    // 남은 시간 포맷 (분:초)
    String timeText;
    if (isPermanent) {
      timeText = '∞';
    } else {
      final seconds = (remainingMs / 1000).ceil();
      final min = seconds ~/ 60;
      final sec = seconds % 60;
      timeText = '$min:${sec.toString().padLeft(2, '0')}';
    }

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
      decoration: BoxDecoration(
        color: Colors.black.withValues(alpha: 0.7),
        borderRadius: BorderRadius.circular(4),
        border: Border.all(color: color.withValues(alpha: 0.7), width: 1),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            icon,
            style: TextStyle(fontSize: 12, color: color),
          ),
          if (label != null) ...[
            const SizedBox(width: 2),
            Text(
              label,
              style: TextStyle(
                fontFamily: 'JetBrainsMono',
                fontSize: 10,
                color: color,
                fontWeight: FontWeight.bold,
              ),
            ),
          ],
          const SizedBox(width: 3),
          Text(
            timeText,
            style: TextStyle(
              fontFamily: 'JetBrainsMono',
              fontSize: 10,
              color: color,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }
}
