namespace Guru
{
    using UnityEngine;
    using System;
    
    
    public partial class GuruSDK
    {
        
        private static AdsInitSpec _adInitSpec;
        
        /// 
        /// 启动广告服务
        /// 
        public static void StartAds(AdsInitSpec spec = null)
        {
            _adInitSpec = spec;
            if (InitConfig.UseCustomConsent)
            {
                UnityEngine.Debug.Log($"{Tag} --- Call StartAdsWithCustomConsent when you use custom consent, and pass the result (boolean) to the method.");
                return;
            }
            
            // 默认的启动顺序是先启动Consent后, 根据用户回调的结果来启动广告
            Instance.StartConsentFlow();
        }
        /// 
        /// 是否已经购买了去广告
        /// 
        /// 
        public static void StartAds(bool buyNoAds = false)
        {
            StartAds(AdsInitSpec.BuildWithNoAds());  // 按照默认的去广告来生成广告启动配置
        }
        /// 
        /// 使用自定义的Consent, 获取用户授权后, 调用此方法
        /// 
        /// 
        /// Consent 引导的类型, 如果使用了 MAX 的 consent 请填写 max 
        /// 广告启动配置
        public static void StartAdsWithCustomConsent(bool userAllow = true, 
            string consentName = "custom", AdsInitSpec spec = null)
        {
#if UNITY_IOS
            _attType = consentName;
            InitAttStatus();
#endif
            if (userAllow)
            {
#if UNITY_IOS
                CheckAttStatus();
#else
                StartAdService(spec);
#endif
            }
            else
            {
                UnityEngine.Debug.Log($"{Tag} --- User refuse to provide ads Id, Ads Service will be cancelled");
            }
        }
        /// 
        /// 使用自定义的Consent, 获取用户授权后, 调用此方法
        /// 
        /// 自定义 Consent 的用户授权结果
        /// Consent引导名称
        /// 是否已经购买了去广告
        [Obsolete("不要再使用自定义的 Consent 流程, 必须使用中台统一的 Consent 流程。 此方法将被废弃")]
        public static void StartAdsWithCustomConsent(bool userAllow = true, string consentName = "custom",
            bool buyNoAds = false)
        {
            var spec = AdsInitSpec.BuildDefault();
            if(buyNoAds)  spec = AdsInitSpec.BuildWithNoAds();
            StartAdsWithCustomConsent(userAllow, consentName, spec);
        }
        #region Guru Consent
        private bool _hasConsentCalled = false;
        private bool _adServiceHasStarted = false;
        /// 
        /// 启动Consent流程
        /// 因为之后规划广告流程会放在 Consent 初始化之后, 因此请求广告的时候会需要先请求 Consent
        /// 
        private void StartConsentFlow()
        {
            float time = 1;
            if (!_adServiceHasStarted && _appServicesConfig != null)
            {
                time = _appServicesConfig.IsAdsCompliance() ? 10 : 1f; // 启动合规判定后, 延迟最多 10 秒后启动广告
            }
            Delay(time, AdServiceHandler); // 广告延迟启动
            
            if (_hasConsentCalled) return;
            _hasConsentCalled = true;
            bool enableCountryCheck = false;
            string dmaMapRule = "";
            
            if (_appServicesConfig != null && _appServicesConfig.parameters != null)
            {
                enableCountryCheck = _appServicesConfig.DMACountryCheck();
                dmaMapRule = _appServicesConfig.DMAMapRule();
            }
#if UNITY_IOS
            InitAttStatus(); // Consent 启动前记录 ATT 初始值
#endif
            UnityEngine.Debug.Log($"{Tag}  --- Call:StartConsentFlow ---");
            GuruConsent.StartConsent(OnGuruConsentOver, dmaMapRule:dmaMapRule, enableCountryCheck:enableCountryCheck);
        }
        /// 
        /// Guru Consent flow is Over
        /// 
        /// 
        private void OnGuruConsentOver(int code)
        {
            
            // 无论状态如何, 都在回调内启动广告初始化
            AdServiceHandler();
            // 调用回调
            Callbacks.ConsentFlow._onConsentResult?.Invoke(code);
            
#if UNITY_IOS
            CheckAttStatus();  // [iOS] Consent 启动后检查 ATT 初始值
#elif UNITY_ANDROID
            CheckPermission(); // [Android] Consent 回调后检查 Push 推送权限
#endif
            
            // 内部处理后继逻辑
            switch(code)
            {
                case GuruConsent.StatusCode.OBTAINED:
                case GuruConsent.StatusCode.NOT_AVAILABLE:
                    // 已获取授权, 或者地区不可用, ATT 尚未启动
                    // TODO: 添加后继处理逻辑
                    break;
            }
        }
        /// 
        /// 启动广告服务
        /// 
        private void AdServiceHandler()
        {
            if (_adServiceHasStarted) return;
            _adServiceHasStarted = true;
            StartAdService(_adInitSpec);
        }
        #endregion
        
        #region IOS ATT 广告授权流程
        
#if UNITY_IOS
        
        private static string _initialAttStatus;
        private static String _attType = "admob";
        private static bool _autoReCallAtt = false;
        
        /// 
        /// 显示系统的 ATT 弹窗
        /// 
        public static void RequestAttDialog()
        {
            LogI($"RequestATTDialog");
            ATTManager.RequestATTDailog(ReportAttStatus);
        }
        
        /// 
        /// 初始化 ATT 状态
        /// 
        public static void InitAttStatus()
        {
            _attType = InitConfig.UseCustomConsent ? ATTManager.GUIDE_TYPE_CUSTOM : ATTManager.GUIDE_TYPE_ADMOB; // 点位属性确定
            _initialAttStatus = ATTManager.GetStatus();
            SetUserProperty(Analytics.ParameterATTStatus, _initialAttStatus); // 上报一个初始的状态
        }
        
        /// 
        /// iOS 平台检查 ATT 状态
        /// 
        private static void CheckAttStatus(bool autoReCall = false)
        {
            _autoReCallAtt = autoReCall;
            
            // Delay 1s to get the user choice
            Delay(1, () => ATTManager.CheckStatus(ReportAttStatus));
        }
        private static void ReportAttStatus(string status)
        {
            LogI($"{Tag} --- Get Att status:{status}  att Type:{_attType}  recall:{_autoReCallAtt}");
            SetUserProperty(Analytics.ParameterATTStatus, status); // 当前的状态
            
            if (!string.IsNullOrEmpty(status) 
                && status != _initialAttStatus 
                && status !=  ATTManager.ATT_STATUS_NOT_DETERMINED)
            {
                // 上报点位:
                Analytics.AttResult(status, _attType);
            }
            switch(status)
            {
                case ATTManager.ATT_STATUS_NOT_DETERMINED:
                    // ATT 状态未知, 请求弹窗
                    if(_autoReCallAtt) RequestAttDialog();
                    break;
                case ATTManager.ATT_STATUS_RESTRICTED:
                case ATTManager.ATT_STATUS_DENIED:
                    // ATT 状态受限, 或者被拒绝
                    break;
                case ATTManager.ATT_STATUS_AUTHORIZED:
                    // ATT 状态已授权
                    break;
            }
        } 
#endif
        
        #endregion
        #region Android 13 PushNotification Permission 
        private const string PERMISSION_POST_NOTIFICATION = "android.permission.POST_NOTIFICATIONS";
        private void CheckPermission()
        {
            float delay = 1;
            UnityEngine.Debug.Log($"---- Check PushPermission ---");
#if UNITY_ANDROID
            // 如果已经请求过权限的话, 则不做动作
            if (UnityEngine.Android.Permission.HasUserAuthorizedPermission(PERMISSION_POST_NOTIFICATION))
            {
                UnityEngine.Debug.Log($"--- PushPermission has passed ---");
                return;
            }
#endif
            Invoke(nameof(RequestNotification), delay);
        }
        /// 
        /// 请求Notification
        /// 
        private void RequestNotification()
        {
#if UNITY_ANDROID
            UnityEngine.Debug.Log("--- Target 33 Request Notification ---");
            // Android直接申请授权
            if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(PERMISSION_POST_NOTIFICATION))
            {
                UnityEngine.Android.Permission.RequestUserPermission(PERMISSION_POST_NOTIFICATION);
            }
#endif
        }
        
        #endregion
        
        #region Ad Services
        private static bool _initAdsCompleted = false;
        private static bool _isBannerVisible = false;
        public static bool IsAdsReady => _initAdsCompleted;
        private static int _preBannerAction = 0;
        
        public static AdsInitSpec GetDefaultAdsSpec()
        {
            return AdsInitSpec.BuildDefault(InitConfig.AutoLoadWhenAdsReady, IsDebugMode);
        }
        /// 
        /// 启动广告服务
        /// 
        internal static void StartAdService(AdsInitSpec spec = null)
        {
            
            //---------- Using InitConfig ----------
            if (InitConfig != null && InitConfig.IsBuyNoAds)
            {
                SetBuyNoAds(true);
                Debug.Log($"[SDK][Ads] ---- StartAdService : {InitConfig.IsBuyNoAds}");
            }
            
            if (spec == null)
            {
                spec = AdsInitSpec.BuildDefault(InitConfig.AutoLoadWhenAdsReady, IsDebugMode);
                if (ADService.Instance.IsBuyNoAds)
                {
                    spec = AdsInitSpec.BuildWithNoAds(InitConfig.AutoLoadWhenAdsReady, IsDebugMode);
                }
            }
            
            if(InitConfig != null && !string.IsNullOrEmpty(InitConfig.BannerBackgroundColor)) 
                spec.bannerColorHex = InitConfig.BannerBackgroundColor;
            
            //--------- Add Callbacks -----------
            // BADS
            ADService.OnBannerStartLoad = OnBannerStartLoad;
            ADService.OnBannerLoaded = OnBannerLoaded;
            // IADS
            ADService.OnInterstitialStartLoad = OnInterstitialStartLoad;
            ADService.OnInterstitialLoaded = OnInterstitialLoaded;
            ADService.OnInterstitialFailed = OnInterstitialFailed;
            // RADS
            ADService.OnRewardedStartLoad = OnRewardedStartLoad;
            ADService.OnRewardLoaded = OnRewardedLoaded;
            ADService.OnRewardFailed = OnRewardedFailed;
            
            // ---------- Start Services ----------
            ADService.Instance.StartService(OnAdsInitComplete, spec);
            
            // ---------- Life Cycle ----------
            Callbacks.App.OnAppPaused += OnAppPaused;
        }
        
        /// 
        /// 生命周期回调
        /// 
        /// 
        private static void OnAppPaused(bool paused)
        {
            if(ADService.Instance.IsInitialized)
                ADService.Instance.OnAppPaused(paused);
        }
        private static void OnBannerStartLoad(string adUnitId)
            => Callbacks.Ads._onBannerADStartLoad?.Invoke(adUnitId);
        private static void OnBannerLoaded() 
            => Callbacks.Ads._onBannerADLoaded?.Invoke();
        private static void OnInterstitialStartLoad(string adUnitId) 
            => Callbacks.Ads._onInterstitialADStartLoad?.Invoke(adUnitId);
        private static void OnInterstitialLoaded() 
            => Callbacks.Ads._onInterstitialADLoaded?.Invoke();
        private static void OnInterstitialFailed()
            => Callbacks.Ads._onInterstitialADFailed?.Invoke();
        private static void OnRewardedStartLoad(string adUnitId)
            => Callbacks.Ads._onRewardedADStartLoad?.Invoke(adUnitId); 
        private static void OnRewardedLoaded()
            => Callbacks.Ads._onRewardedADLoaded?.Invoke(); 
        private static void OnRewardedFailed()
            => Callbacks.Ads._onRewardADFailed?.Invoke();
        private static void OnAdsInitComplete()
        {
            _initAdsCompleted = true;
            if (_adInitSpec != null && _adInitSpec.loadBanner)
            {
                // 预制动作处理
                if (_preBannerAction == 1)
                {
                    _preBannerAction = 0;
                    ShowBanner();
                }
                else if (_preBannerAction == -1)
                {
                    _preBannerAction = 0;
                    HideBanner();
                }
            }
            Callbacks.Ads._onAdsInitComplete?.Invoke();
        }
        private static bool CheckAdsReady()
        {
            if (!IsAdsReady)
            {
                LogW("[SDK] Ads is not ready. Call  first.");
                return false;
            }
            return true;
        }
        /// 
        /// 显示Banner广告
        /// 
        /// 
        public static void ShowBanner(string placement = "")
        {
            if (!CheckAdsReady())
            {
                _preBannerAction = 1;
                return;
            }
            ADService.Instance.ShowBanner(placement);
        }
        
        /// 
        /// 设置 Banner 背景颜色
        /// 
        /// 
        public static void SetBannerBackgroundColor(Color color)
        {
            // if (!CheckAdsReady()) return;
            ADService.Instance.SetBannerBackgroundColor(color);
        }
        
        public static void SetBannerAutoRefresh(bool value = true)
        {
            if (!CheckAdsReady()) return;
            ADService.Instance.SetBannerAutoRefresh(value);
        }
        
        /// 
        /// 隐藏Banner广告
        /// 
        public static void HideBanner()
        {
            if (!CheckAdsReady())
            {
                _preBannerAction = -1;
                return;
            }
            ADService.Instance.HideBanner();
        }
        public static void LoadInterstitialAd()
        {
            if (!CheckAdsReady()) return;
            ADService.Instance.RequestInterstitialAD();
        }
        public static bool IsInterstitialAdReady => ADService.Instance.IsInterstitialADReady();
        
        /// 
        /// 显示插屏广告
        /// 
        /// 
        /// 
        public static void ShowInterstitialAd(string placement = "", Action onDismissed = null)
        {
            if (!CheckAdsReady()) return;
            if (!ADService.Instance.IsInterstitialADReady())
            {
                LogE("Interstitial is not ready. Call  again.");
                LoadInterstitialAd();
                return;
            }
            ADService.Instance.ShowInterstitialAD(placement, onDismissed);
        }
        public static void LoadRewardAd()
        {
            if (!CheckAdsReady()) return;
            ADService.Instance.RequestRewardedAD();
        }
        
        public static bool IsRewardAdReady => ADService.Instance.IsRewardedADReady();
        
        /// 
        /// 显示激励视频广告
        /// 
        /// 
        /// 
        /// 
        public static void ShowRewardAd(string placement = "", Action onRewarded = null, Action onFailed = null)
        {
            if (!CheckAdsReady()) return;
            if (!ADService.Instance.IsRewardedADReady())
            {
                LogE("RewardAd is not ready. Call  again.");
                LoadRewardAd();
                return;
            }
            ADService.Instance.ShowRewardedAD(placement, onRewarded, onFailed);
        }
        #endregion
        #region MaxServices
        /// 
        /// 显示Max调试菜单
        /// 
        public static void ShowMaxDebugPanel()
        {
#if UNITY_EDITOR
            LogI($"Can not show Max Debug Panel in Editor, skipped.");
            return;
#endif
            if (!ADService.Instance.IsInitialized)
            {
                LogI($"ADService is not initialized, call  first.");
                return;
            }
            ADService.Instance.ShowMaxDebugPanel();
        }
        #endregion
    }
    
}