import 'dart:async';

import 'package:asciineverdie/data/story_data.dart';

/// 스토리 이벤트 타입 (Story Event Type)
enum StoryEventType {
  actStart, // Act 시작
  actComplete, // Act 완료
  bossEncounter, // 보스 조우
  bossDefeat, // 보스 처치
  ending, // 엔딩
}

/// 스토리 이벤트 (Story Event)
class StoryEvent {
  const StoryEvent({required this.type, required this.act, this.data});

  final StoryEventType type;
  final StoryAct act;
  final Map<String, dynamic>? data;
}

/// 스토리 서비스 (Phase 9: Story Progression Management)
///
/// Act 전환, 시네마틱 트리거, 보스 조우 관리
class StoryService {
  StoryService();

  final _eventController = StreamController<StoryEvent>.broadcast();

  /// 스토리 이벤트 스트림 (Story Event Stream)
  Stream<StoryEvent> get events => _eventController.stream;

  // 현재 Act 추적
  StoryAct _currentAct = StoryAct.prologue;
  bool _hasSeenPrologue = false;
  final Set<StoryAct> _completedActs = {};

  /// 현재 Act (Current Act)
  StoryAct get currentAct => _currentAct;

  /// 프롤로그 시청 여부
  bool get hasSeenPrologue => _hasSeenPrologue;

  /// 완료된 Act 목록
  Set<StoryAct> get completedActs => Set.unmodifiable(_completedActs);

  /// 레벨 변화 감지 및 Act 전환 처리 (Process Level Change)
  ///
  /// 레벨업 시 호출하여 Act 전환 이벤트 트리거
  StoryEvent? processLevelChange(int oldLevel, int newLevel) {
    final oldAct = getActForLevel(oldLevel);
    final newAct = getActForLevel(newLevel);

    // 새 게임 시작 (프롤로그)
    if (oldLevel == 0 && newLevel == 1 && !_hasSeenPrologue) {
      _hasSeenPrologue = true;
      _currentAct = StoryAct.prologue;
      final event = StoryEvent(
        type: StoryEventType.actStart,
        act: StoryAct.prologue,
      );
      _eventController.add(event);
      return event;
    }

    // Act 전환 감지
    if (newAct != oldAct && newAct != _currentAct) {
      // 이전 Act 완료 처리
      if (_currentAct != StoryAct.prologue) {
        _completedActs.add(_currentAct);
        _eventController.add(
          StoryEvent(type: StoryEventType.actComplete, act: _currentAct),
        );
      }

      // 새 Act 시작
      _currentAct = newAct;
      final event = StoryEvent(type: StoryEventType.actStart, act: newAct);
      _eventController.add(event);
      return event;
    }

    return null;
  }

  /// 보스 조우 처리 (Process Boss Encounter)
  void processBossEncounter(String monsterName) {
    // BOSS: 접두사가 있는 몬스터인지 확인
    if (!monsterName.startsWith('BOSS:')) return;

    final event = StoryEvent(
      type: StoryEventType.bossEncounter,
      act: _currentAct,
      data: {'bossName': monsterName},
    );
    _eventController.add(event);
  }

  /// 보스 처치 처리 (Process Boss Defeat)
  void processBossDefeat(String monsterName) {
    if (!monsterName.startsWith('BOSS:')) return;

    final event = StoryEvent(
      type: StoryEventType.bossDefeat,
      act: _currentAct,
      data: {'bossName': monsterName},
    );
    _eventController.add(event);

    // 최종 보스 처치 시 엔딩
    if (monsterName.contains('Primordial Glitch')) {
      _triggerEnding();
    }
  }

  /// 엔딩 트리거 (Trigger Ending)
  void _triggerEnding() {
    _completedActs.add(StoryAct.act5);
    _currentAct = StoryAct.ending;
    _eventController.add(
      StoryEvent(type: StoryEventType.ending, act: StoryAct.ending),
    );
  }

  /// 시네마틱 데이터 가져오기 (Get Cinematic Data)
  List<CinematicStep> getCinematicSteps(StoryAct act) {
    return cinematicData[act] ?? [];
  }

  /// Act 제목 가져오기 (Get Act Title)
  String getActTitle(StoryAct act) {
    return actTitles[act] ?? 'Unknown';
  }

  /// Act 보스 이름 가져오기 (Get Act Boss Name)
  String? getActBossName(StoryAct act) {
    return actBossNames[act];
  }

  /// 저장 데이터로 상태 복원 (Restore State from Save)
  void restoreState({
    required StoryAct currentAct,
    required bool hasSeenPrologue,
    required Set<StoryAct> completedActs,
  }) {
    _currentAct = currentAct;
    _hasSeenPrologue = hasSeenPrologue;
    _completedActs
      ..clear()
      ..addAll(completedActs);
  }

  /// 현재 상태를 저장 데이터로 변환 (Convert to Save Data)
  Map<String, dynamic> toSaveData() {
    return {
      'currentAct': _currentAct.index,
      'hasSeenPrologue': _hasSeenPrologue,
      'completedActs': _completedActs.map((a) => a.index).toList(),
    };
  }

  /// 저장 데이터에서 복원 (Restore from Save Data)
  void fromSaveData(Map<String, dynamic> data) {
    _currentAct = StoryAct.values[data['currentAct'] as int? ?? 0];
    _hasSeenPrologue = data['hasSeenPrologue'] as bool? ?? false;
    final completedIndices = data['completedActs'] as List<dynamic>? ?? [];
    _completedActs
      ..clear()
      ..addAll(completedIndices.map((i) => StoryAct.values[i as int]));
  }

  /// 서비스 정리 (Dispose)
  void dispose() {
    _eventController.close();
  }
}
