import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:asciineverdie/src/core/engine/ad_service.dart';
import 'package:asciineverdie/src/core/engine/iap_service.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';

/// 캐릭터 생성 굴리기/되돌리기 서비스
///
/// 굴리기 횟수 제한과 되돌리기 기능을 관리합니다.
/// - 굴리기: 5회 (0회 시 광고 시청으로 충전)
/// - 되돌리기: 무료 유저 1회(광고), 유료 유저 3회(무료)
class CharacterRollService {
  CharacterRollService._();

  static CharacterRollService? _instance;

  /// 싱글톤 인스턴스
  static CharacterRollService get instance {
    _instance ??= CharacterRollService._();
    return _instance!;
  }

  // ===========================================================================
  // 상수
  // ===========================================================================

  /// 저장 키
  static const String _rollsRemainingKey = 'char_rolls_remaining';

  /// 최대 굴리기 횟수
  static const int maxRolls = 5;

  /// 최대 되돌리기 횟수 (무료 유저)
  static const int maxUndoFreeUser = 1;

  /// 최대 되돌리기 횟수 (유료 유저)
  static const int maxUndoPaidUser = 3;

  // ===========================================================================
  // 상태
  // ===========================================================================

  bool _isInitialized = false;

  /// 남은 굴리기 횟수
  int _rollsRemaining = maxRolls;

  /// 남은 되돌리기 횟수
  int _undoRemaining = maxUndoFreeUser;

  /// 되돌리기용 스탯 히스토리
  final List<RollSnapshot> _rollHistory = [];

  // ===========================================================================
  // 초기화
  // ===========================================================================

  /// 서비스 초기화
  Future<void> initialize() async {
    if (_isInitialized) return;

    await _loadState();
    _resetUndoForNewSession();

    _isInitialized = true;
    debugPrint(
      '[CharacterRollService] Initialized: '
      'rolls=$_rollsRemaining, undo=$_undoRemaining',
    );
  }

  /// 저장된 상태 로드
  Future<void> _loadState() async {
    final prefs = await SharedPreferences.getInstance();
    _rollsRemaining = prefs.getInt(_rollsRemainingKey) ?? maxRolls;
  }

  /// 굴리기 횟수 저장
  Future<void> _saveRollsRemaining() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt(_rollsRemainingKey, _rollsRemaining);
    debugPrint('[CharacterRollService] Saved rolls: $_rollsRemaining');
  }

  /// 새 세션 시작 시 되돌리기 초기화
  void _resetUndoForNewSession() {
    _undoRemaining = _isPaidUser ? maxUndoPaidUser : maxUndoFreeUser;
    _rollHistory.clear();
  }

  // ===========================================================================
  // 유료 사용자 확인
  // ===========================================================================

  /// 유료 사용자 여부
  bool get _isPaidUser => IAPService.instance.isAdRemovalPurchased;

  // ===========================================================================
  // 굴리기
  // ===========================================================================

  /// 남은 굴리기 횟수
  int get rollsRemaining => _rollsRemaining;

  /// 굴리기 가능 여부
  bool get canRoll => _rollsRemaining > 0;

  /// 굴리기 실행
  ///
  /// [currentStats] 현재 스탯 (되돌리기용 저장)
  /// [currentRaceIndex] 현재 종족 인덱스
  /// [currentKlassIndex] 현재 직업 인덱스
  /// [currentSeed] 현재 RNG 시드
  /// Returns: 굴리기 성공 여부
  bool roll({
    required Stats currentStats,
    required int currentRaceIndex,
    required int currentKlassIndex,
    required int currentSeed,
  }) {
    if (!canRoll) {
      debugPrint('[CharacterRollService] Cannot roll: no rolls remaining');
      return false;
    }

    // 현재 상태를 히스토리에 저장
    _rollHistory.insert(
      0,
      RollSnapshot(
        stats: currentStats,
        raceIndex: currentRaceIndex,
        klassIndex: currentKlassIndex,
        seed: currentSeed,
      ),
    );

    // 최대 히스토리 개수 제한 (되돌리기 가능 횟수만큼)
    final maxHistory = _isPaidUser ? maxUndoPaidUser : maxUndoFreeUser;
    while (_rollHistory.length > maxHistory) {
      _rollHistory.removeLast();
    }

    // 굴리기 횟수 감소
    _rollsRemaining--;
    _saveRollsRemaining();

    // 매 굴림마다 되돌리기 횟수 리셋
    // - 유료 유저: 3회
    // - 무료 유저: 1회 (광고 시청 필요)
    _undoRemaining = _isPaidUser ? maxUndoPaidUser : maxUndoFreeUser;

    debugPrint(
      '[CharacterRollService] Rolled: remaining=$_rollsRemaining, '
      'history=${_rollHistory.length}, undo=$_undoRemaining',
    );

    return true;
  }

  /// 광고 시청 후 굴리기 충전
  Future<bool> rechargeRollsWithAd() async {
    // 유료 사용자는 광고 없이 충전
    if (_isPaidUser) {
      _rollsRemaining = maxRolls;
      await _saveRollsRemaining();
      debugPrint('[CharacterRollService] Recharged (paid user): $maxRolls');
      return true;
    }

    // 인터스티셜 광고 표시
    final result = await AdService.instance.showInterstitialAd(
      adType: AdType.interstitialRoll,
      onComplete: () {
        _rollsRemaining = maxRolls;
        _saveRollsRemaining();
      },
    );

    if (result == AdResult.completed || result == AdResult.debugSkipped) {
      debugPrint('[CharacterRollService] Recharged with ad: $maxRolls');
      return true;
    }

    debugPrint('[CharacterRollService] Recharge failed: $result');
    return false;
  }

  // ===========================================================================
  // 되돌리기
  // ===========================================================================

  /// 남은 되돌리기 횟수
  int get undoRemaining => _undoRemaining;

  /// 되돌리기 히스토리 길이
  int get historyLength => _rollHistory.length;

  /// 실제 사용 가능한 되돌리기 횟수
  /// min(undoRemaining, historyLength)
  int get availableUndos {
    final available = _undoRemaining < _rollHistory.length
        ? _undoRemaining
        : _rollHistory.length;
    return available;
  }

  /// 되돌리기 가능 여부
  bool get canUndo => availableUndos > 0;

  /// 되돌리기 실행 (유료 사용자)
  ///
  /// Returns: 복원된 스냅샷 (null이면 실패)
  RollSnapshot? undoPaidUser() {
    if (!_isPaidUser) return null;
    if (!canUndo) return null;

    final snapshot = _rollHistory.removeAt(0);
    _undoRemaining--;

    debugPrint(
      '[CharacterRollService] Undo (paid): '
      'remaining=$_undoRemaining, history=${_rollHistory.length}',
    );

    return snapshot;
  }

  /// 되돌리기 실행 (무료 사용자 - 광고 필요)
  ///
  /// [onSuccess] 광고 시청 완료 후 콜백
  Future<RollSnapshot?> undoFreeUser() async {
    if (_isPaidUser) return undoPaidUser();
    if (!canUndo) return null;

    // 리워드 광고 표시
    RollSnapshot? result;

    final adResult = await AdService.instance.showRewardedAd(
      adType: AdType.rewardUndo,
      onRewarded: () {
        if (_rollHistory.isNotEmpty) {
          result = _rollHistory.removeAt(0);
          _undoRemaining--;
        }
      },
    );

    if (adResult == AdResult.completed || adResult == AdResult.debugSkipped) {
      debugPrint(
        '[CharacterRollService] Undo (free with ad): '
        'remaining=$_undoRemaining, history=${_rollHistory.length}',
      );
      return result;
    }

    debugPrint('[CharacterRollService] Undo failed: $adResult');
    return null;
  }

  // ===========================================================================
  // 캐릭터 생성 완료
  // ===========================================================================

  /// 캐릭터 생성 완료 시 호출
  ///
  /// 되돌리기 상태만 초기화 (굴리기 횟수는 유지)
  void onCharacterCreated() {
    _resetUndoForNewSession();
    debugPrint('[CharacterRollService] Character created, undo reset');
  }

  /// 굴리기 횟수 완전 초기화 (디버그용)
  Future<void> resetRolls() async {
    _rollsRemaining = maxRolls;
    await _saveRollsRemaining();
    _resetUndoForNewSession();
    debugPrint('[CharacterRollService] Reset all');
  }
}

/// 굴리기 스냅샷 (되돌리기용)
class RollSnapshot {
  const RollSnapshot({
    required this.stats,
    required this.raceIndex,
    required this.klassIndex,
    required this.seed,
  });

  final Stats stats;
  final int raceIndex;
  final int klassIndex;
  final int seed;
}
