// =============================================================================
// TudadaSDK Example
//
// TudadaSDK의 모든 주요 기능을 보여주는 예제입니다.
// 실제 프로젝트에서는 필요한 기능만 선택적으로 사용하세요.
//
// 사용법:
// 1. 씬에 빈 GameObject를 생성합니다.
// 2. 이 스크립트를 추가합니다.
// 3. Play 모드에서 테스트합니다.
// =============================================================================

using System;
using UnityEngine;
using UnityEngine.UI;
using Tudada;

// 본 예제는 @deprecated CreateRewardedVideoAd/TudadaRewardedVideoAd 사용을 시연하므로
// 파일 전역에서 CS0618(Obsolete) 경고를 억제한다. 신규 연동은 ShowRewardedAd(slot) 권장.
#pragma warning disable CS0618

/// <summary>
/// TudadaSDK 사용 예제
/// </summary>
public class TudadaSDKExample : MonoBehaviour
{
    #region Constants

    private const string LOG_PREFIX = "[TudadaExample]";

    #endregion

    #region Serialized Fields

    [Header("광고 설정")]
    [Tooltip("보상형 비디오 광고 단위 ID")]
    [SerializeField] private string _adUnitId = "your-ad-unit-id";

    [Header("UI 참조 (선택)")]
    [SerializeField] private Text _statusText;
    [SerializeField] private Button _loginButton;
    [SerializeField] private Button _showAdButton;

    #endregion

    #region Private Fields

    private TudadaRewardedVideoAd _rewardedAd;
    private PlayerData _playerData;

    #endregion

    #region Unity Lifecycle

    private void Start()
    {
        Log("TudadaSDK Example 시작");

        if (TudadaSDK.Instance.IsAvailable())
        {
            Log("TudadaSDK 사용 가능");
            InitializeSDK();
        }
        else
        {
            LogError("TudadaSDK를 사용할 수 없습니다");
        }

        SetupUI();
    }

    private void OnDestroy()
    {
        UnregisterEvents();
        _rewardedAd?.Destroy();
    }

    #endregion

    #region Initialization

    private void InitializeSDK()
    {
        RegisterEvents();
        PrintSystemInfo();
        PerformLogin();
    }

    private void RegisterEvents()
    {
        TudadaSDK.OnShow += OnAppShow;
        TudadaSDK.OnHide += OnAppHide;
        TudadaSDK.OnKeyboardInput += OnKeyboardInput;
        TudadaSDK.OnKeyboardConfirm += OnKeyboardConfirm;
        TudadaSDK.OnKeyboardComplete += OnKeyboardComplete;
    }

    private void UnregisterEvents()
    {
        TudadaSDK.OnShow -= OnAppShow;
        TudadaSDK.OnHide -= OnAppHide;
        TudadaSDK.OnKeyboardInput -= OnKeyboardInput;
        TudadaSDK.OnKeyboardConfirm -= OnKeyboardConfirm;
        TudadaSDK.OnKeyboardComplete -= OnKeyboardComplete;
    }

    private void SetupUI()
    {
        if (_loginButton != null)
        {
            _loginButton.onClick.AddListener(PerformLogin);
        }

        if (_showAdButton != null)
        {
            _showAdButton.onClick.AddListener(ShowRewardedAd);
            _showAdButton.interactable = false;
        }
    }

    #endregion

    #region Auth Examples

    private void PerformLogin()
    {
        Log("로그인 시도...");

        TudadaSDK.Instance.Login(
            onSuccess: result =>
            {
                Log($"로그인 성공! 코드: {result.code}");
                GetUserInfo();
                LoadPlayerData();
                PrepareRewardedAd();
            },
            onFail: err => LogError($"로그인 실패: {err}"),
            timeout: 10000
        );
    }

    private void GetUserInfo()
    {
        TudadaSDK.Instance.GetUserInfo(
            onSuccess: result =>
            {
                Log($"사용자 정보 - 닉네임: {result.userInfo.nickName}");
                Log($"사용자 정보 - 언어: {result.userInfo.language}");
            },
            onFail: err => LogError($"사용자 정보 조회 실패: {err}")
        );
    }

    /// <summary>
    /// 세션 유효성 확인 예제 (필요 시 호출)
    /// </summary>
    public void CheckSessionExample()
    {
        TudadaSDK.Instance.CheckSession(
            onSuccess: _ => Log("세션 유효함"),
            onFail: _ =>
            {
                Log("세션 만료됨 - 재로그인 필요");
                PerformLogin();
            }
        );
    }

    #endregion

    #region Storage Examples

    private void LoadPlayerData()
    {
        Log("플레이어 데이터 로드 중...");

        TudadaSDK.Instance.TudadaStoreGet("playerData",
            onSuccess: result =>
            {
                if (!string.IsNullOrEmpty(result.value))
                {
                    try
                    {
                        _playerData = JsonUtility.FromJson<PlayerData>(result.value);
                        Log($"플레이어 데이터 로드 성공 - 점수: {_playerData.score}, 레벨: {_playerData.level}");
                    }
                    catch (Exception e)
                    {
                        LogError($"플레이어 데이터 파싱 실패: {e.Message}");
                        _playerData = new PlayerData();
                    }
                }
                else
                {
                    Log("저장된 플레이어 데이터 없음 - 새로 생성");
                    _playerData = new PlayerData();
                }
            },
            onFail: err =>
            {
                LogError($"플레이어 데이터 로드 실패: {err}");
                _playerData = new PlayerData();
            }
        );
    }

    /// <summary>
    /// 플레이어 데이터 저장 (외부에서 호출 가능)
    /// </summary>
    public void SavePlayerData()
    {
        if (_playerData == null) return;

        string json = JsonUtility.ToJson(_playerData);
        Log($"플레이어 데이터 저장 중... ({json.Length} bytes)");

        TudadaSDK.Instance.TudadaStoreSave("playerData", json,
            onSuccess: _ => Log("플레이어 데이터 저장 성공"),
            onFail: err => LogError($"플레이어 데이터 저장 실패: {err}")
        );
    }

    /// <summary>
    /// 로컬 스토리지 사용 예제 (필요 시 호출)
    /// </summary>
    public void LocalStorageExample()
    {
        // 동기 방식
        TudadaSDK.Instance.SetStorageSync("lastPlayTime", DateTime.Now.ToString());
        string lastPlayTime = TudadaSDK.Instance.GetStorageSync("lastPlayTime");
        Log($"마지막 플레이 시간: {lastPlayTime}");

        // 비동기 방식
        TudadaSDK.Instance.SetStorage("highScore", "9999",
            onSuccess: _ =>
            {
                TudadaSDK.Instance.GetStorage("highScore",
                    onSuccess: getResult => Log($"최고 점수: {getResult.data}")
                );
            }
        );

        // 스토리지 정보
        var info = TudadaSDK.Instance.GetStorageInfoSync();
        Log($"스토리지 사용량: {info.currentSize}KB / {info.limitSize}KB");
    }

    #endregion

    #region System Info Examples

    private void PrintSystemInfo()
    {
        // 시스템 정보 (Tudada.SystemInfo를 명시적으로 사용)
        var sysInfo = TudadaSDK.Instance.GetSystemInfoSync();
        Log("=== 시스템 정보 ===");
        Log($"SDK 버전: {sysInfo.SDKVersion}");
        Log($"화면 크기: {sysInfo.screenWidth}x{sysInfo.screenHeight}");
        Log($"플랫폼: {sysInfo.platform}");
        Log($"브랜드: {sysInfo.brand}, 모델: {sysInfo.model}");

        // 창 정보
        var winInfo = TudadaSDK.Instance.GetWindowInfo();
        Log($"창 크기: {winInfo.windowWidth}x{winInfo.windowHeight}");
        Log($"SafeArea: L{winInfo.safeArea.left} T{winInfo.safeArea.top} R{winInfo.safeArea.right} B{winInfo.safeArea.bottom}");

    }

    #endregion

    #region Device Examples

    /// <summary>
    /// 짧은 진동 예제
    /// </summary>
    public void VibrateExample()
    {
        TudadaSDK.Instance.VibrateShort(VibrateType.medium,
            onSuccess: _ => Log("짧은 진동 완료")
        );
    }

    /// <summary>
    /// 긴 진동 예제
    /// </summary>
    public void VibrateLongExample()
    {
        TudadaSDK.Instance.VibrateLong(
            onSuccess: _ => Log("긴 진동 완료")
        );
    }

    /// <summary>
    /// 키보드 표시 예제
    /// </summary>
    public void ShowKeyboardExample()
    {
        TudadaSDK.Instance.ShowKeyboard(
            defaultValue: "",
            maxLength: 20,
            multiple: false,
            confirmHold: false,
            confirmType: KeyboardConfirmType.done,
            onSuccess: _ => Log("키보드 표시됨")
        );
    }

    /// <summary>
    /// 키보드 숨김 예제
    /// </summary>
    public void HideKeyboardExample()
    {
        TudadaSDK.Instance.HideKeyboard(
            onSuccess: _ => Log("키보드 숨김")
        );
    }

    /// <summary>
    /// 클립보드 예제
    /// </summary>
    public void ClipboardExample()
    {
        TudadaSDK.Instance.SetClipboardData("Hello from TudadaSDK!",
            onSuccess: _ =>
            {
                Log("클립보드에 복사됨");

                TudadaSDK.Instance.GetClipboardData(
                    onSuccess: getResult => Log($"클립보드 내용: {getResult.data}")
                );
            }
        );
    }

    #endregion

    #region Ad Examples

    private void PrepareRewardedAd()
    {
        Log("광고 준비 중...");

        _rewardedAd = TudadaSDK.Instance.CreateRewardedVideoAd(_adUnitId);

        _rewardedAd.OnLoad += () =>
        {
            Log("광고 로드 완료");
            if (_showAdButton != null)
            {
                _showAdButton.interactable = true;
            }
        };

        _rewardedAd.OnError += error => LogError($"광고 에러: {error.errMsg} (코드: {error.errCode})");

        _rewardedAd.OnClose += OnAdClosed;

        _rewardedAd.Load(
            onSuccess: _ => Log("광고 로드 요청 성공"),
            onFail: err => LogError($"광고 로드 실패: {err}")
        );
    }

    /// <summary>
    /// 보상형 광고 표시
    /// </summary>
    public void ShowRewardedAd()
    {
        if (_rewardedAd == null)
        {
            LogError("광고 인스턴스가 없습니다");
            return;
        }

        if (!_rewardedAd.IsLoaded)
        {
            Log("광고가 아직 로드되지 않았습니다");
            return;
        }

        _rewardedAd.Show(
            onSuccess: _ => Log("광고 표시됨"),
            onFail: err => LogError($"광고 표시 실패: {err}")
        );
    }

    /// <summary>
    /// (신규·권장) 통합 리워드 슬롯 API 예시 — GetRewardedAdSlots 로 슬롯을 조회하고
    /// 첫 슬롯을 ShowRewardedAd(slot) 으로 실행한다. slotData 는 null 일 수 있어 접근 전 체크한다.
    /// </summary>
    public void ShowRewardedAdSlotExample()
    {
        TudadaSDK.Instance.GetRewardedAdSlots(
            onSuccess: res =>
            {
                if (res.slots == null || res.slots.Length == 0)
                {
                    Log("리워드 슬롯 없음");
                    return;
                }

                var slot = res.slots[0];
                // slotData 는 기본 video/share 슬롯에서 null 일 수 있다 — 접근 전 null 체크 필수
                string imageUrl = slot.slotData != null ? slot.slotData.imageUrl : "(없음)";
                Log($"슬롯: {slot.slotId} / action: {slot.action} / image: {imageUrl}");

                TudadaSDK.Instance.ShowRewardedAd(
                    slot,
                    onSuccess: r => Log(r.isEnded ? "리워드 완료 - 보상 지급" : "리워드 미완료"),
                    onFail: err => LogError($"리워드 실행 실패: {err}")
                );
            },
            onFail: err => LogError($"슬롯 조회 실패: {err}")
        );
    }

    private void OnAdClosed(AdCloseResult result)
    {
        if (result.isEnded)
        {
            Log("광고 시청 완료! 보상 지급");
            GiveReward();
        }
        else
        {
            Log("광고 중간에 종료됨");
        }

        // 다음 광고 미리 로드
        if (_rewardedAd != null && !_rewardedAd.IsDestroyed)
        {
            if (_showAdButton != null)
            {
                _showAdButton.interactable = false;
            }
            _rewardedAd.Load();
        }
    }

    private void GiveReward()
    {
        if (_playerData == null) return;

        _playerData.score += 100;
        Log($"보상 지급! 현재 점수: {_playerData.score}");
        SavePlayerData();
    }

    #endregion

    #region Lifecycle Examples

    private void OnAppShow(OnShowResult result)
    {
        Log($"앱 포그라운드 전환 - 경로: {result.path}, 씬: {result.scene}");
        // 게임 재개 로직 추가
    }

    private void OnAppHide(OnHideResult result)
    {
        Log("앱 백그라운드 전환");
        SavePlayerData();
    }

    /// <summary>
    /// 앱 종료 예제
    /// </summary>
    public void ExitAppExample()
    {
        Log("앱 종료 요청...");
        SavePlayerData();

        TudadaSDK.Instance.ExitMiniProgram(
            onSuccess: _ => Log("앱 종료 성공")
        );
    }

    /// <summary>
    /// 앱 재시작 예제
    /// </summary>
    public void RestartAppExample()
    {
        Log("앱 재시작 요청...");

        TudadaSDK.Instance.RestartMiniProgram(
            onSuccess: _ => Log("앱 재시작 성공")
        );
    }

    #endregion

    #region Keyboard Event Handlers

    private void OnKeyboardInput(KeyboardInputResult result)
    {
        Log($"키보드 입력: {result.value}");
    }

    private void OnKeyboardConfirm(KeyboardConfirmResult result)
    {
        Log($"키보드 확인: {result.value}");
    }

    private void OnKeyboardComplete(KeyboardCompleteResult result)
    {
        Log($"키보드 완료: {result.value}");
    }

    #endregion

    #region Logging Helpers

    private void Log(string message)
    {
        Debug.Log($"{LOG_PREFIX} {message}");
        UpdateStatusText(message);
    }

    private void LogError(string message)
    {
        Debug.LogError($"{LOG_PREFIX} {message}");
        UpdateStatusText($"ERROR: {message}");
    }

    private void UpdateStatusText(string message)
    {
        if (_statusText != null)
        {
            _statusText.text = message;
        }
    }

    #endregion
}

#region Example Data Classes

/// <summary>
/// 플레이어 데이터 (예시용)
/// </summary>
/// <remarks>
/// 실제 프로젝트에서는 별도 파일로 분리하세요.
/// </remarks>
[Serializable]
public class PlayerData
{
    /// <summary>
    /// 플레이어 점수
    /// </summary>
    public int score;

    /// <summary>
    /// 플레이어 레벨
    /// </summary>
    public int level;

    /// <summary>
    /// 마지막 저장 시간
    /// </summary>
    public string lastSaveTime;

    /// <summary>
    /// 새 플레이어 데이터 생성
    /// </summary>
    public PlayerData()
    {
        score = 0;
        level = 1;
        lastSaveTime = DateTime.Now.ToString("O");
    }
}

#endregion
#pragma warning restore CS0618
