import 'dart:io';

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

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

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

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

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

/// 광고 결과
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 콘솔에서 생성 후 교체)
  // ─────────────────────────────────────────────────────────────────────────
  // TODO: AdMob 콘솔에서 광고 단위 생성 후 아래 ID 교체
  static const String _prodRewardedAndroid =
      'ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX'; // Android 리워드 광고
  static const String _prodRewardedIos =
      'ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX'; // iOS 리워드 광고
  static const String _prodInterstitialAndroid =
      'ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX'; // Android 인터스티셜 광고
  static const String _prodInterstitialIos =
      'ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX'; // iOS 인터스티셜 광고

  /// 리워드 광고 단위 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;

  /// 디버그 모드에서 광고 활성화 여부
  bool _debugAdEnabled = true;

  /// 로드된 리워드 광고
  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();
  }

  // ===========================================================================
  // 디버그 설정
  // ===========================================================================

  /// 디버그 모드 광고 활성화 여부
  bool get debugAdEnabled => _debugAdEnabled;

  /// 디버그 모드 광고 토글
  set debugAdEnabled(bool value) {
    _debugAdEnabled = value;
    debugPrint('[AdService] Debug ad enabled: $value');
  }

  /// 광고를 스킵할지 여부
  ///
  /// 스킵 조건:
  /// - 비모바일 플랫폼 (macOS, Windows, Linux, Web)
  /// - 디버그 모드에서 광고 비활성화
  bool get _shouldSkipAd {
    // 웹에서는 항상 스킵
    if (kIsWeb) return true;
    // 비모바일 플랫폼(데스크톱)에서는 항상 스킵
    if (!Platform.isAndroid && !Platform.isIOS) {
      return true;
    }
    // 디버그 모드에서 광고 비활성화 시 스킵
    return kDebugMode && !_debugAdEnabled;
  }

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

  /// 리워드 광고 로드
  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;

    // 결과 추적용
    var result = AdResult.cancelled;

    ad.fullScreenContentCallback = FullScreenContentCallback(
      onAdDismissedFullScreenContent: (ad) {
        debugPrint('[AdService] Rewarded ad dismissed');
        ad.dispose();
        _loadRewardedAd(); // 다음 광고 미리 로드
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        debugPrint('[AdService] Rewarded ad failed to show: ${error.message}');
        ad.dispose();
        result = AdResult.failed;
        _loadRewardedAd();
      },
    );

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

    return result;
  }

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

  /// 인터스티셜 광고 로드
  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;

    // 결과 추적용
    var result = AdResult.cancelled;

    ad.fullScreenContentCallback = FullScreenContentCallback(
      onAdDismissedFullScreenContent: (ad) {
        debugPrint('[AdService] Interstitial ad dismissed');
        ad.dispose();
        result = AdResult.completed;
        onComplete();
        _loadInterstitialAd(); // 다음 광고 미리 로드
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        debugPrint(
          '[AdService] Interstitial ad failed to show: ${error.message}',
        );
        ad.dispose();
        result = AdResult.failed;
        _loadInterstitialAd();
      },
    );

    await ad.show();

    return result;
  }

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

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

    _interstitialAd?.dispose();
    _interstitialAd = null;

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