import 'dart:math' as math;

import 'package:asciineverdie/data/game_text_l10n.dart' as l10n;
import 'package:asciineverdie/src/shared/animation/monster_size.dart';
import 'package:asciineverdie/src/core/engine/combat_calculator.dart';
import 'package:asciineverdie/src/core/model/combat_state.dart';
import 'package:asciineverdie/src/core/model/combat_stats.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/monster_combat_stats.dart';
import 'package:asciineverdie/src/core/model/monster_grade.dart';
import 'package:asciineverdie/src/core/model/pq_config.dart';
import 'package:asciineverdie/src/core/util/balance_constants.dart';
import 'package:asciineverdie/src/core/util/pq_logic.dart' as pq_logic;

/// Act 진행 관련 로직을 처리하는 서비스
///
/// ProgressService에서 추출된 Act 완료, 보스 생성 등의 로직 담당.
class ActProgressionService {
  const ActProgressionService({required this.config});

  final PqConfig config;

  /// Act 완료 처리
  ///
  /// 플롯 진행, Act Boss 시네마틱 후 호출.
  /// Returns gameComplete=true if Final Boss was defeated (game ends).
  ({GameState state, bool gameComplete}) completeAct(GameState state) {
    // Act V 완료 시 (plotStageCount == 6) → 최종 보스 전투 시작
    // plotStageCount: 1=Prologue, 2=Act I, 3=Act II, 4=Act III, 5=Act IV, 6=Act V
    if (state.progress.plotStageCount >= 6) {
      // 이미 최종 보스가 처치되었으면 게임 클리어
      if (state.progress.finalBossState == FinalBossState.defeated) {
        final updatedPlotHistory = [
          ...state.progress.plotHistory.map(
            (e) => e.isComplete ? e : e.copyWith(isComplete: true),
          ),
          const HistoryEntry(caption: '*** THE END ***', isComplete: true),
        ];

        final updatedProgress = state.progress.copyWith(
          plotHistory: updatedPlotHistory,
        );

        return (
          state: state.copyWith(progress: updatedProgress),
          gameComplete: true,
        );
      }

      // 최종 보스가 아직 등장하지 않았으면 보스 전투 시작
      if (state.progress.finalBossState == FinalBossState.notSpawned) {
        final updatedProgress = state.progress.copyWith(
          finalBossState: FinalBossState.fighting,
        );

        // 게임은 아직 끝나지 않음 - 보스 전투 진행
        return (
          state: state.copyWith(progress: updatedProgress),
          gameComplete: false,
        );
      }

      // 보스 전투 중이면 계속 진행 (게임 종료 안 함)
      return (state: state, gameComplete: false);
    }

    final actResult = pq_logic.completeAct(state.progress.plotStageCount);
    var nextState = state;

    // 보상 처리는 호출자(ProgressService)가 담당
    // 여기서는 플롯 상태만 업데이트

    final plotStages = nextState.progress.plotStageCount + 1;

    // 플롯 히스토리 업데이트: 이전 플롯 완료 표시, 새 플롯 추가
    final updatedPlotHistory = [
      ...nextState.progress.plotHistory.map(
        (e) => e.isComplete ? e : e.copyWith(isComplete: true),
      ),
      HistoryEntry(caption: actResult.actTitle, isComplete: false),
    ];

    var updatedProgress = nextState.progress.copyWith(
      plot: ProgressBarState(position: 0, max: actResult.plotBarMaxSeconds),
      plotStageCount: plotStages,
      plotHistory: updatedPlotHistory,
    );

    nextState = nextState.copyWith(progress: updatedProgress);

    // Act I 완료 후(Prologue -> Act I) 첫 퀘스트 시작 (원본 Main.pas 로직)
    // plotStages == 2는 Prologue(1) -> Act I(2) 전환을 의미
    if (plotStages == 2) {
      nextState = startFirstQuest(nextState);
    }

    return (state: nextState, gameComplete: false);
  }

  /// Act 완료 시 적용할 보상 목록 반환
  List<pq_logic.RewardKind> getActRewards(int plotStageCount) {
    final actResult = pq_logic.completeAct(plotStageCount);
    return actResult.rewards;
  }

  /// 첫 퀘스트 시작 (Act I 시작 시)
  GameState startFirstQuest(GameState state) {
    final result = pq_logic.completeQuest(
      config,
      state.rng,
      state.traits.level,
    );

    // 퀘스트 바 초기화
    final questBar = ProgressBarState(
      position: 0,
      max: 50 + state.rng.nextInt(100),
    );

    // 첫 퀘스트 히스토리 추가
    final questHistory = [
      HistoryEntry(caption: result.caption, isComplete: false),
    ];

    // 퀘스트 몬스터 정보 저장 (Exterminate 타입용)
    final questMonster = result.monsterIndex != null
        ? QuestMonsterInfo(
            monsterData: result.monsterName!,
            monsterIndex: result.monsterIndex!,
          )
        : null;

    // 첫 퀘스트 추가
    final updatedQueue = QueueState(
      entries: [
        ...state.queue.entries,
        QueueEntry(
          kind: QueueKind.task,
          durationMillis: 50 + state.rng.nextInt(100),
          caption: result.caption,
          taskType: TaskType.neutral,
        ),
      ],
    );

    final progress = state.progress.copyWith(
      quest: questBar,
      questCount: 1,
      questHistory: questHistory,
      currentQuestMonster: questMonster,
    );

    return state.copyWith(progress: progress, queue: updatedQueue);
  }

  /// Act Boss 생성 (Act 완료 시)
  ///
  /// 보스 레벨 = min(플레이어 레벨, Act 최소 레벨)로 설정하여
  /// 플레이어가 이길 수 있는 수준 보장
  CombatState createActBoss(GameState state) {
    final plotStage = state.progress.plotStageCount;
    final actNumber = plotStage + 1;

    // 보스 레벨 = min(플레이어 레벨, Act 최소 레벨)
    // → 플레이어가 현재 레벨보다 높은 보스를 만나지 않도록 보장
    final actMinLevel = ActMonsterLevel.forPlotStage(actNumber);
    final bossLevel = math.min(state.traits.level, actMinLevel);

    // Named monster 생성 (pq_logic.namedMonster 활용)
    final bossName = pq_logic.namedMonster(config, state.rng, bossLevel);

    final bossStats = MonsterBaseStats.forLevel(bossLevel);

    // 플레이어 전투 스탯 생성
    final playerCombatStats = CombatStats.fromStats(
      stats: state.stats,
      equipment: state.equipment,
      level: state.traits.level,
      monsterLevel: bossLevel,
    );

    // Boss 몬스터 스탯 생성 (일반 몬스터 대비 강화)
    final monsterCombatStats = MonsterCombatStats(
      name: bossName,
      level: bossLevel,
      atk: (bossStats.atk * 1.5).round(), // Boss 보정 (1.5배)
      def: (bossStats.def * 1.5).round(),
      magDef: (bossStats.def * 1.8).round(), // 보스 마법 방어 (물리 대비 1.2배)
      hpMax: (bossStats.hp * 2.0).round(), // HP는 2.0배 (보스다운 전투 시간)
      hpCurrent: (bossStats.hp * 2.0).round(),
      criRate: 0.05,
      criDamage: 1.5,
      evasion: 0.0,
      accuracy: 0.8,
      attackDelayMs: 1000,
      expReward: (bossStats.exp * 2.5).round(), // 경험치 보상 증가
    );

    // 전투 상태 초기화
    return CombatState.start(
      playerStats: playerCombatStats,
      monsterStats: monsterCombatStats,
    );
  }

  /// 최종 보스(Glitch God) 전투 시작
  ///
  /// Act V 플롯 완료 후 호출되며, 글리치 갓과의 전투를 설정합니다.
  ({ProgressState progress, QueueState queue}) startFinalBossFight(
    GameState state,
    ProgressState progress,
    QueueState queue,
  ) {
    final level = state.traits.level;

    // Glitch God 생성 (레벨 100 최종 보스)
    final glitchGod = MonsterCombatStats.glitchGod();

    // 플레이어 전투 스탯 생성 (Phase 12: 보스 레벨 기반 페널티 적용)
    final playerCombatStats = CombatStats.fromStats(
      stats: state.stats,
      equipment: state.equipment,
      level: level,
      monsterLevel: glitchGod.level,
    );

    // 전투 상태 초기화
    final combatState = CombatState.start(
      playerStats: playerCombatStats,
      monsterStats: glitchGod,
    );

    // 전투 시간 추정 (보스 전투는 더 길게)
    final combatCalculator = CombatCalculator(rng: state.rng);
    final baseDuration = combatCalculator.estimateCombatDurationMs(
      player: playerCombatStats,
      monster: glitchGod,
    );
    // 최종 보스는 최소 10초, 최대 60초
    final durationMillis = baseDuration.clamp(10000, 60000);

    final taskResult = pq_logic.startTask(
      progress,
      l10n.taskFinalBoss(glitchGod.name),
      durationMillis,
    );

    final updatedProgress = taskResult.progress.copyWith(
      currentTask: TaskInfo(
        caption: taskResult.caption,
        type: TaskType.kill,
        monsterBaseName: 'Glitch God',
        monsterPart: '*', // 특수 전리품
        monsterLevel: glitchGod.level,
        monsterGrade: MonsterGrade.boss, // 최종 보스는 항상 boss 등급
        monsterSize: MonsterSize.large, // 최종 보스는 항상 대형
      ),
      currentCombat: combatState,
    );

    return (progress: updatedProgress, queue: queue);
  }
}
