using System;
using Unity.Services.LevelPlay;

public class LevelPlayInterstitialAdProvider : IInterstitialAdProvider
{
    public string Name { get => "levelplay"; }

    public event EventHandler<double> OnAdLoaded;
    public event EventHandler<string> OnAdLoadFailed;
    public event EventHandler OnAdShown;
    public event EventHandler<string> OnAdShowFailed;
    public event EventHandler OnAdClosed;
    public event EventHandler<AdRevenueReceivedEventArgs> OnAdRevenueReceived;

    private string LevelPlayInterstitialAdUnitId { get; }

    private LevelPlayInterstitialAd InterstitialAd { get; set; }

    public LevelPlayInterstitialAdProvider(string adUnitId)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Constructor] LevelPlayInterstitialAdProvider()");

        LevelPlayInterstitialAdUnitId = adUnitId;

        InstantiateInterstitialAd();
    }

    public void LoadInterstitialAd(double priceFloor = 0d)
    {
        AdHelper.Log($"[LevelPlayInterstitialAdProvider] [Method] LoadInterstitialAd(priceFloor: {priceFloor})");

        InterstitialAd?.LoadAd();
    }

    public void NotifyLoss(string winnerDemandId, double ecpm)
    {
        AdHelper.Log($"[LevelPlayInterstitialAdProvider] [Method] NotifyLoss(winner: {winnerDemandId}, ecpm: {ecpm})");

        InstantiateInterstitialAd();
    }

    public void NotifyWin()
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Method] NotifyWin()");
    }

    public void ShowInterstitialAd(string placementName)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Method] ShowInterstitialAd()");

        InterstitialAd?.ShowAd(placementName);
    }

    private void InstantiateInterstitialAd()
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Method] InstantiateInterstitialAd()");

        if (InterstitialAd != null)
        {
            UnsubscribeFromInterstitialAdEvents(InterstitialAd);
            InterstitialAd.DestroyAd();
        }

        InterstitialAd = new LevelPlayInterstitialAd(LevelPlayInterstitialAdUnitId);
        SubscribeToInterstitialAdEvents(InterstitialAd);
    }

    private void SubscribeToInterstitialAdEvents(LevelPlayInterstitialAd ad)
    {
        if (ad == null) return;

        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Method] SubscribeToInterstitialAdEvents()");

        ad.OnAdLoaded += OnLevelPlayInterstitialAdLoaded;
        ad.OnAdLoadFailed += OnLevelPlayInterstitialAdLoadFailed;
        ad.OnAdDisplayed += OnLevelPlayInterstitialAdDisplayed;
        ad.OnAdDisplayFailed += OnLevelPlayInterstitialAdDisplayFailed;
        ad.OnAdClosed += OnLevelPlayInterstitialAdClosed;
    }

    private void UnsubscribeFromInterstitialAdEvents(LevelPlayInterstitialAd ad)
    {
        if (ad == null) return;

        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Method] UnsubscribeFromInterstitialAdEvents()");

        ad.OnAdLoaded -= OnLevelPlayInterstitialAdLoaded;
        ad.OnAdLoadFailed -= OnLevelPlayInterstitialAdLoadFailed;
        ad.OnAdDisplayed -= OnLevelPlayInterstitialAdDisplayed;
        ad.OnAdDisplayFailed -= OnLevelPlayInterstitialAdDisplayFailed;
        ad.OnAdClosed -= OnLevelPlayInterstitialAdClosed;
    }

    private void OnLevelPlayInterstitialAdLoaded(LevelPlayAdInfo adInfo)
    {
        double ecpm = AdHelper.GetRoundedEcpm((adInfo.Revenue ?? 0d) * 1000);
        AdHelper.Log($"[LevelPlayInterstitialAdProvider] [Callback] OnLevelPlayInterstitialAdLoaded(ecpm: {ecpm}). Revenue is {adInfo.Revenue}");

        OnAdLoaded?.Invoke(this, ecpm);
    }

    private void OnLevelPlayInterstitialAdLoadFailed(LevelPlayAdError error)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Callback] OnLevelPlayInterstitialAdLoadFailed()");

        OnAdLoadFailed?.Invoke(this, error.ToString());
    }

    private void OnLevelPlayInterstitialAdDisplayed(LevelPlayAdInfo adInfo)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Callback] OnLevelPlayInterstitialAdDisplayed()");

        OnAdShown?.Invoke(this, EventArgs.Empty);

        var info = new AdInfo
        {
            AdType = "Interstitial",
            AdUnitId = adInfo.AdUnitId,
            CurrencyCode = "USD",
            MediationId = Name,
            NetworkAdUnitId = adInfo.InstanceId,
            NetworkName = adInfo.AdNetwork,
            Revenue = adInfo.Revenue ?? 0d,
            RevenuePrecision = adInfo.Precision,
        };
        OnAdRevenueReceived?.Invoke(this, new AdRevenueReceivedEventArgs(info));
    }

    private void OnLevelPlayInterstitialAdDisplayFailed(LevelPlayAdDisplayInfoError infoError)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Callback] OnLevelPlayInterstitialAdDisplayFailed()");

        InstantiateInterstitialAd();
        OnAdShowFailed?.Invoke(this, infoError.ToString());
    }

    private void OnLevelPlayInterstitialAdClosed(LevelPlayAdInfo adInfo)
    {
        AdHelper.Log("[LevelPlayInterstitialAdProvider] [Callback] OnLevelPlayInterstitialAdClosed()");

        InstantiateInterstitialAd();
        OnAdClosed?.Invoke(this, EventArgs.Empty);
    }
}
