// =============================================================================
// TudadaRewardedVideoAd
//
// 보상형 비디오 광고 인스턴스
// TudadaSDK.Instance.CreateRewardedVideoAd()로 생성합니다.
//
// 사용 예시:
// var ad = TudadaSDK.Instance.CreateRewardedVideoAd("ad-unit-id");
// ad.OnLoad += () => Debug.Log("광고 로드 완료");
// ad.OnError += (err) => Debug.LogError($"광고 에러: {err.errMsg}");
// ad.OnClose += (res) => { if (res.isEnded) GiveReward(); };
// ad.Load();
// =============================================================================

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using Tudada;
using Tudada.Internal;

/// <summary>
/// 보상형 비디오 광고 인스턴스
/// </summary>
[System.Obsolete("wx 호환 레거시 타입입니다. ShowRewardedAd() 를 사용하세요. 다음 버전에서 제거될 예정입니다.")]
public class TudadaRewardedVideoAd
{
    #region DllImport

#if UNITY_WEBGL && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void TudadaSDK_AdLoad(int adInstanceId, int callbackId);

    [DllImport("__Internal")]
    private static extern void TudadaSDK_AdShow(int adInstanceId, int callbackId);

    [DllImport("__Internal")]
    private static extern void TudadaSDK_AdDestroy(int adInstanceId);
#endif

    #endregion

    #region Static Instance Management

    private static readonly Dictionary<int, TudadaRewardedVideoAd> _instances = new Dictionary<int, TudadaRewardedVideoAd>();
    private static int _nextInstanceId;

    /// <summary>
    /// 인스턴스 ID로 광고 인스턴스 조회
    /// </summary>
    /// <param name="instanceId">인스턴스 ID</param>
    /// <returns>광고 인스턴스 (없으면 null)</returns>
    internal static TudadaRewardedVideoAd GetInstance(int instanceId)
    {
        return _instances.TryGetValue(instanceId, out var ad) ? ad : null;
    }

    #endregion

    #region Properties

    /// <summary>
    /// 광고 인스턴스 ID
    /// </summary>
    public int InstanceId { get; private set; }

    /// <summary>
    /// 광고 단위 ID
    /// </summary>
    public string AdUnitId { get; private set; }

    /// <summary>
    /// 광고가 로드되었는지 여부
    /// </summary>
    public bool IsLoaded { get; private set; }

    /// <summary>
    /// 광고가 파괴되었는지 여부
    /// </summary>
    public bool IsDestroyed { get; private set; }

    #endregion

    #region Events

    /// <summary>
    /// 광고 로드 완료 이벤트
    /// </summary>
    public event Action OnLoad;

    /// <summary>
    /// 광고 에러 이벤트
    /// </summary>
    public event Action<AdErrorResult> OnError;

    /// <summary>
    /// 광고 닫기 이벤트
    /// </summary>
    public event Action<AdCloseResult> OnClose;

    #endregion

    #region Constructor

    /// <summary>
    /// TudadaRewardedVideoAd 생성자
    /// 직접 호출하지 마세요. TudadaSDK.Instance.CreateRewardedVideoAd()를 사용하세요.
    /// </summary>
    /// <param name="adUnitId">광고 단위 ID</param>
    internal TudadaRewardedVideoAd(string adUnitId)
    {
        AdUnitId = adUnitId;
        InstanceId = _nextInstanceId++;
        IsLoaded = false;
        IsDestroyed = false;

        _instances[InstanceId] = this;

        LogDebug($"Created - instanceId: {InstanceId}, adUnitId: {adUnitId}");
    }

    #endregion

    #region Public Methods

    /// <summary>
    /// 광고 로드
    /// </summary>
    /// <param name="onSuccess">성공 콜백</param>
    /// <param name="onFail">실패 콜백</param>
    public void Load(Action<AdLoadResult> onSuccess = null, Action<string> onFail = null)
    {
        if (IsDestroyed)
        {
            LogWarning("Cannot load destroyed ad");
            onFail?.Invoke(Messages.AD_DESTROYED);
            return;
        }

        LogDebug($"Load - instanceId: {InstanceId}");

#if UNITY_WEBGL && !UNITY_EDITOR
        int callbackId = TudadaSDK.Instance.RegisterAdCallback(
            json =>
            {
                IsLoaded = true;
                InvokeSuccessCallback(json, onSuccess, new AdLoadResult { errMsg = Messages.AD_LOAD_OK });
            },
            errMsg =>
            {
                IsLoaded = false;
                onFail?.Invoke(errMsg);
            }
        );
        TudadaSDK_AdLoad(InstanceId, callbackId);
#else
        LogEditor("Load simulated");
        IsLoaded = true;
        onSuccess?.Invoke(new AdLoadResult { errMsg = Messages.AD_LOAD_OK });
        OnLoad?.Invoke();
#endif
    }

    /// <summary>
    /// 광고 표시
    /// </summary>
    /// <param name="onSuccess">성공 콜백</param>
    /// <param name="onFail">실패 콜백</param>
    public void Show(Action<AdShowResult> onSuccess = null, Action<string> onFail = null)
    {
        if (IsDestroyed)
        {
            LogWarning("Cannot show destroyed ad");
            onFail?.Invoke(Messages.AD_DESTROYED);
            return;
        }

        if (!IsLoaded)
        {
            LogWarning("Ad is not loaded yet");
            onFail?.Invoke(Messages.AD_NOT_LOADED);
            return;
        }

        LogDebug($"Show - instanceId: {InstanceId}");

#if UNITY_WEBGL && !UNITY_EDITOR
        int callbackId = TudadaSDK.Instance.RegisterAdCallback(
            json => InvokeSuccessCallback(json, onSuccess, new AdShowResult { errMsg = Messages.AD_SHOW_OK }),
            onFail
        );
        TudadaSDK_AdShow(InstanceId, callbackId);
#else
        LogEditor("Show simulated");
        onSuccess?.Invoke(new AdShowResult { errMsg = Messages.AD_SHOW_OK });
        OnClose?.Invoke(new AdCloseResult { isEnded = true });
        IsLoaded = false;
#endif
    }

    /// <summary>
    /// 광고 인스턴스 파괴
    /// </summary>
    public void Destroy()
    {
        if (IsDestroyed)
        {
            LogWarning("Ad is already destroyed");
            return;
        }

        LogDebug($"Destroy - instanceId: {InstanceId}");

#if UNITY_WEBGL && !UNITY_EDITOR
        TudadaSDK_AdDestroy(InstanceId);
#endif

        _instances.Remove(InstanceId);
        IsDestroyed = true;
        IsLoaded = false;
        OnLoad = null;
        OnError = null;
        OnClose = null;
    }

    #endregion

    #region Internal Event Triggers

    /// <summary>
    /// OnLoad 이벤트 트리거 (jslib에서 호출)
    /// </summary>
    internal void TriggerOnLoad()
    {
        LogDebug($"TriggerOnLoad - instanceId: {InstanceId}");
        IsLoaded = true;
        OnLoad?.Invoke();
    }

    /// <summary>
    /// OnError 이벤트 트리거 (jslib에서 호출)
    /// </summary>
    /// <param name="error">에러 정보</param>
    internal void TriggerOnError(AdErrorResult error)
    {
        LogDebug($"TriggerOnError - instanceId: {InstanceId}, errMsg: {error.errMsg}");
        OnError?.Invoke(error);
    }

    /// <summary>
    /// OnClose 이벤트 트리거 (jslib에서 호출)
    /// </summary>
    /// <param name="result">닫기 결과</param>
    internal void TriggerOnClose(AdCloseResult result)
    {
        LogDebug($"TriggerOnClose - instanceId: {InstanceId}, isEnded: {result.isEnded}");
        IsLoaded = false;
        OnClose?.Invoke(result);
    }

    #endregion

    #region Helper Methods

    private void InvokeSuccessCallback<T>(string json, Action<T> onSuccess, T defaultValue) where T : class
    {
        if (onSuccess == null) return;

        try
        {
            var result = JsonUtility.FromJson<T>(json);
            onSuccess.Invoke(result ?? defaultValue);
        }
        catch
        {
            onSuccess.Invoke(defaultValue);
        }
    }

    private void LogDebug(string message)
    {
        Debug.Log($"{Constants.AD_LOG_PREFIX} {message}");
    }

    private void LogWarning(string message)
    {
        Debug.LogWarning($"{Constants.AD_LOG_PREFIX} {message}");
    }

    private void LogEditor(string message)
    {
        Debug.Log($"{Constants.AD_LOG_PREFIX} {Constants.EDITOR_LOG_SUFFIX} {message}");
    }

    #endregion
}
