import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

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

/// 광고 타입
enum AdType {
  /// 부활용 리워드 광고 (30초)
  rewardRevive,

  /// 캐릭터 생성 되돌리기용 리워드 광고 (30초)
  rewardUndo,

  /// 굴리기 충전용 인터스티셜 광고 (6초)
  interstitialRoll,

  /// 속도업용 인터스티셜 광고 (6초)
  interstitialSpeed,

  /// 복귀 보상용 리워드 광고 (30초)
  rewardReturn,
}

/// 광고 결과
enum AdResult {
  /// 광고 시청 완료 (보상 지급)
  completed,

  /// 광고 시청 취소/스킵
  cancelled,

  /// 광고 로드 실패
  failed,

  /// 디버그 모드에서 광고 스킵
  debugSkipped,
}

/// 광고 서비스
///
/// AdMob 리워드/인터스티셜 광고 로드 및 표시를 관리합니다.
/// 디버그 모드에서는 광고 ON/OFF 토글이 가능합니다.
class AdService {
  AdService._();

  static AdService? _instance;

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

  // ===========================================================================
  // 광고 단위 ID
  // ===========================================================================

  // ─────────────────────────────────────────────────────────────────────────
  // 테스트 광고 ID (Google 공식 테스트 ID)
  // ─────────────────────────────────────────────────────────────────────────
  static const String _testRewardedAndroid =
      'ca-app-pub-3940256099942544/5224354917';
  static const String _testRewardedIos =
      'ca-app-pub-3940256099942544/1712485313';
  static const String _testInterstitialAndroid =
      'ca-app-pub-3940256099942544/1033173712';
  static const String _testInterstitialIos =
      'ca-app-pub-3940256099942544/4411468910';

  // ─────────────────────────────────────────────────────────────────────────
  // 프로덕션 광고 ID (AdMob 콘솔에서 생성 후 교체)
  // ─────────────────────────────────────────────────────────────────────────
  static const String _prodRewardedAndroid =
      'ca-app-pub-6691216385521068/3457464395'; // Android 리워드 광고
  // TODO(ios): AdMob iOS 광고 ID — iOS 출시 전 필수 교체
  static const String _prodRewardedIos = _testRewardedIos;
  static const String _prodInterstitialAndroid =
      'ca-app-pub-6691216385521068/1625507977'; // Android 인터스티셜 광고
  // TODO(ios): AdMob iOS 광고 ID — iOS 출시 전 필수 교체
  static const String _prodInterstitialIos = _testInterstitialIos;

  /// 리워드 광고 단위 ID (릴리즈 빌드: 프로덕션 ID, 디버그 빌드: 테스트 ID)
  String get _rewardAdUnitId {
    if (Platform.isAndroid) {
      return kReleaseMode ? _prodRewardedAndroid : _testRewardedAndroid;
    } else if (Platform.isIOS) {
      return kReleaseMode ? _prodRewardedIos : _testRewardedIos;
    }
    return '';
  }

  /// 인터스티셜 광고 단위 ID (릴리즈 빌드: 프로덕션 ID, 디버그 빌드: 테스트 ID)
  String get _interstitialAdUnitId {
    if (Platform.isAndroid) {
      return kReleaseMode ? _prodInterstitialAndroid : _testInterstitialAndroid;
    } else if (Platform.isIOS) {
      return kReleaseMode ? _prodInterstitialIos : _testInterstitialIos;
    }
    return '';
  }

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

  bool _isInitialized = false;

  /// 로드된 리워드 광고
  RewardedAd? _rewardedAd;

  /// 로드된 인터스티셜 광고
  InterstitialAd? _interstitialAd;

  /// 리워드 광고 로딩 중 여부
  bool _isLoadingRewardedAd = false;

  /// 인터스티셜 광고 로딩 중 여부
  bool _isLoadingInterstitialAd = false;

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

  /// AdMob SDK 초기화
  Future<void> initialize() async {
    if (_isInitialized) return;

    // 모바일 플랫폼에서만 초기화
    if (!Platform.isAndroid && !Platform.isIOS) {
      debugPrint('[AdService] Non-mobile platform, skipping initialization');
      return;
    }

    await MobileAds.instance.initialize();
    _isInitialized = true;
    debugPrint('[AdService] Initialized');

    // 초기 광고 로드
    _loadRewardedAd();
    _loadInterstitialAd();
  }

  // ===========================================================================
  // 광고 스킵 판정
  // ===========================================================================

  /// 광고를 스킵할지 여부
  ///
  /// 스킵 조건:
  /// - 비모바일 플랫폼 (macOS, Windows, Linux, Web)
  /// - IAP로 광고 제거 구매 완료 (디버그 시뮬레이션 포함)
  bool get _shouldSkipAd {
    // 웹에서는 항상 스킵
    if (kIsWeb) return true;
    // 비모바일 플랫폼(데스크톱)에서는 항상 스킵
    if (!Platform.isAndroid && !Platform.isIOS) {
      return true;
    }
    // IAP 광고 제거 구매 시 스킵 (디버그 시뮬레이션 포함)
    if (IAPService.instance.isAdRemovalPurchased) return true;
    return false;
  }

  // ===========================================================================
  // 리워드 광고
  // ===========================================================================

  /// 리워드 광고 로드
  void _loadRewardedAd() {
    if (_isLoadingRewardedAd || _rewardedAd != null) return;
    if (!_isInitialized) return;

    _isLoadingRewardedAd = true;
    debugPrint('[AdService] Loading rewarded ad...');

    RewardedAd.load(
      adUnitId: _rewardAdUnitId,
      request: const AdRequest(),
      rewardedAdLoadCallback: RewardedAdLoadCallback(
        onAdLoaded: (ad) {
          _rewardedAd = ad;
          _isLoadingRewardedAd = false;
          debugPrint('[AdService] Rewarded ad loaded');
        },
        onAdFailedToLoad: (error) {
          _isLoadingRewardedAd = false;
          debugPrint(
            '[AdService] Rewarded ad failed to load: ${error.message}',
          );
        },
      ),
    );
  }

  /// 리워드 광고 준비 여부
  bool get isRewardedAdReady => _rewardedAd != null || _shouldSkipAd;

  /// 리워드 광고 표시
  ///
  /// [adType] 광고 타입 (로깅용)
  /// [onRewarded] 보상 지급 콜백
  /// Returns: 광고 결과
  Future<AdResult> showRewardedAd({
    required AdType adType,
    required void Function() onRewarded,
  }) async {
    // 디버그 모드에서 광고 스킵
    if (_shouldSkipAd) {
      debugPrint('[AdService] Debug: Skipping $adType ad');
      onRewarded();
      return AdResult.debugSkipped;
    }

    // 광고가 로드되지 않은 경우
    if (_rewardedAd == null) {
      debugPrint('[AdService] Rewarded ad not ready');
      _loadRewardedAd();
      return AdResult.failed;
    }

    final ad = _rewardedAd!;
    _rewardedAd = null;

    // Completer를 사용하여 광고 종료까지 대기
    final completer = Completer<AdResult>();
    var rewarded = false;

    // 광고 표시 전 전체 화면 모드로 전환 (상단 UI 숨김)
    await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);

    ad.fullScreenContentCallback = FullScreenContentCallback(
      onAdDismissedFullScreenContent: (ad) {
        debugPrint('[AdService] Rewarded ad dismissed');
        // 광고 종료 후 UI 복원
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: SystemUiOverlay.values,
        );
        ad.dispose();
        _loadRewardedAd(); // 다음 광고 미리 로드
        // 보상 수령 여부에 따라 결과 반환
        if (!completer.isCompleted) {
          completer.complete(
            rewarded ? AdResult.completed : AdResult.cancelled,
          );
        }
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        debugPrint('[AdService] Rewarded ad failed to show: ${error.message}');
        // 광고 실패 시에도 UI 복원
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: SystemUiOverlay.values,
        );
        ad.dispose();
        _loadRewardedAd();
        if (!completer.isCompleted) {
          completer.complete(AdResult.failed);
        }
      },
    );

    await ad.show(
      onUserEarnedReward: (ad, reward) {
        debugPrint('[AdService] User earned reward: ${reward.amount}');
        rewarded = true;
        onRewarded();
      },
    );

    // 광고가 종료될 때까지 대기
    return completer.future;
  }

  // ===========================================================================
  // 인터스티셜 광고
  // ===========================================================================

  /// 인터스티셜 광고 로드
  void _loadInterstitialAd() {
    if (_isLoadingInterstitialAd || _interstitialAd != null) return;
    if (!_isInitialized) return;

    _isLoadingInterstitialAd = true;
    debugPrint('[AdService] Loading interstitial ad...');

    InterstitialAd.load(
      adUnitId: _interstitialAdUnitId,
      request: const AdRequest(),
      adLoadCallback: InterstitialAdLoadCallback(
        onAdLoaded: (ad) {
          _interstitialAd = ad;
          _isLoadingInterstitialAd = false;
          debugPrint('[AdService] Interstitial ad loaded');
        },
        onAdFailedToLoad: (error) {
          _isLoadingInterstitialAd = false;
          debugPrint(
            '[AdService] Interstitial ad failed to load: ${error.message}',
          );
        },
      ),
    );
  }

  /// 인터스티셜 광고 준비 여부
  bool get isInterstitialAdReady => _interstitialAd != null || _shouldSkipAd;

  /// 인터스티셜 광고 표시
  ///
  /// [adType] 광고 타입 (로깅용)
  /// [onComplete] 광고 완료 콜백 (보상 지급)
  /// Returns: 광고 결과
  Future<AdResult> showInterstitialAd({
    required AdType adType,
    required void Function() onComplete,
  }) async {
    // 디버그 모드에서 광고 스킵
    if (_shouldSkipAd) {
      debugPrint('[AdService] Debug: Skipping $adType ad');
      onComplete();
      return AdResult.debugSkipped;
    }

    // 광고가 로드되지 않은 경우
    if (_interstitialAd == null) {
      debugPrint('[AdService] Interstitial ad not ready');
      _loadInterstitialAd();
      return AdResult.failed;
    }

    final ad = _interstitialAd!;
    _interstitialAd = null;

    // Completer를 사용하여 광고 종료까지 대기
    final completer = Completer<AdResult>();

    // 광고 표시 전 전체 화면 모드로 전환 (상단 UI 숨김)
    await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);

    ad.fullScreenContentCallback = FullScreenContentCallback(
      onAdDismissedFullScreenContent: (ad) {
        debugPrint('[AdService] Interstitial ad dismissed');
        // 광고 종료 후 UI 복원
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: SystemUiOverlay.values,
        );
        ad.dispose();
        onComplete();
        _loadInterstitialAd(); // 다음 광고 미리 로드
        if (!completer.isCompleted) {
          completer.complete(AdResult.completed);
        }
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        debugPrint(
          '[AdService] Interstitial ad failed to show: ${error.message}',
        );
        // 광고 실패 시에도 UI 복원
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: SystemUiOverlay.values,
        );
        ad.dispose();
        onComplete();
        _loadInterstitialAd();
        if (!completer.isCompleted) {
          completer.complete(AdResult.failed);
        }
      },
    );

    await ad.show();

    // 광고가 종료될 때까지 대기
    return completer.future;
  }

  // ===========================================================================
  // 정리
  // ===========================================================================

  /// 리소스 해제
  void dispose() {
    _rewardedAd?.dispose();
    _rewardedAd = null;

    _interstitialAd?.dispose();
    _interstitialAd = null;

    debugPrint('[AdService] Disposed');
  }
}
