using System;
using UnityEngine;

namespace MJGameSDK
{
    /// <summary>
    /// 平台上报：游戏激活、界面阶段、创角/登角。
    /// 服/角色数据由游戏侧维护，SDK 负责按阶段上报；device_id 必填，其余字段有则传。
    /// </summary>
    public class MJGameAnalytics
    {
        public const string EventLoadingUi = "loading_ui";
        public const string EventLoginUi = "login_ui";
        public const string EventLoadingGame = "loading_game";
        public const string EventEnterGame = "enter_game";

        private readonly MJGameHttpClient _http;

        public MJGameAnalytics(MJGameHttpClient http)
        {
            _http = http;
        }

        /// <summary>
        /// 收集当前设备与环境信息，供激活/阶段上报使用。
        /// </summary>
        public static MJGameActivateInfo CollectActivateInfo()
        {
            var ctx = MJGameClientContext.Instance;
            if (ctx != null)
            {
                return new MJGameActivateInfo
                {
                    device_id = ctx.DeviceId,
                    device_model = ctx.DeviceModel,
                    os = ctx.Os,
                    os_version = ctx.OsVersion,
                    app_version = ctx.AppVersion,
                    sdk_version = ctx.SdkVersion,
                    language = ctx.Language
                };
            }

            return new MJGameActivateInfo
            {
                device_id = SystemInfo.deviceUniqueIdentifier,
                device_model = SystemInfo.deviceModel,
                os = Application.platform.ToString(),
                os_version = SystemInfo.operatingSystem,
                app_version = Application.version,
                sdk_version = MJGameSDKVersion.Version,
                language = MJGameClientContext.ResolveLanguageCode()
            };
        }

        /// <summary>
        /// 合并设备信息与可选角色信息，供阶段上报使用。
        /// </summary>
        public static MJGameLifecycleInfo CollectLifecycleInfo(MJGameRoleInfo role = null)
        {
            var activate = CollectActivateInfo();
            var info = new MJGameLifecycleInfo
            {
                device_id = activate.device_id,
                device_model = activate.device_model,
                os = activate.os,
                os_version = activate.os_version,
                app_version = activate.app_version,
                sdk_version = activate.sdk_version,
                language = activate.language
            };

            if (role != null)
            {
                info.server_id = role.server_id;
                info.server_name = role.server_name;
                info.role_id = role.role_id;
                info.role_name = role.role_name;
                info.role_level = role.role_level;
                info.role_class = role.role_class;
            }

            return info;
        }

        /// <summary>
        /// 上报游戏激活（SDK 初始化完成后调用，无需登录；服务端同步写入 role_events.activate）。
        /// 设备信息由 SDK 内部自动采集，游戏无需传入。
        /// </summary>
        public void ReportGameActivate(Action onSuccess = null, Action<MJGameResult> onError = null)
        {
            var info = CollectActivateInfo();
            if (string.IsNullOrEmpty(info.device_id))
            {
                onError?.Invoke(MJGameResult.Fail(5001, "device_id is required"));
                return;
            }

            _http.Post<AnalyticsResponse>("events/game-activate", info,
                _ =>
                {
                    MJGameLogger.Info("Analytics", $"Game activate reported: device={info.device_id}");
                    onSuccess?.Invoke();
                },
                onError);
        }

        /// <summary>
        /// 上报加载界面（无需登录，角色信息通常尚未就绪）。
        /// </summary>
        public void ReportLoadingUI(Action onSuccess = null, Action<MJGameResult> onError = null)
        {
            ReportUiStage(EventLoadingUi, "Loading UI", onSuccess, onError);
        }

        /// <summary>
        /// 上报登录界面（无需登录，角色信息通常尚未就绪）。
        /// </summary>
        public void ReportLoginUI(Action onSuccess = null, Action<MJGameResult> onError = null)
        {
            ReportUiStage(EventLoginUi, "Login UI", onSuccess, onError);
        }

        /// <summary>
        /// 上报加载游戏（需已登录；建议传入完整角色信息）。
        /// </summary>
        public void ReportLoadingGame(MJGameRoleInfo roleInfo, Action onSuccess = null, Action<MJGameResult> onError = null)
        {
            ReportGameStage(EventLoadingGame, roleInfo, "Loading game", onSuccess, onError);
        }

        /// <summary>
        /// 上报进入游戏（需已登录；建议传入完整角色信息）。
        /// </summary>
        public void ReportEnterGame(MJGameRoleInfo roleInfo, Action onSuccess = null, Action<MJGameResult> onError = null)
        {
            ReportGameStage(EventEnterGame, roleInfo, "Enter game", onSuccess, onError);
        }

        /// <summary>
        /// 上报创建角色（玩家首次进入该角色时调用，需已登录）。
        /// </summary>
        public void ReportRoleCreate(MJGameRoleInfo roleInfo, Action onSuccess, Action<MJGameResult> onError)
        {
            ReportRoleEvent("events/role-create", roleInfo, "Role create", onSuccess, onError);
        }

        /// <summary>
        /// 上报登录角色（玩家每次进入角色时调用，需已登录）。
        /// </summary>
        public void ReportRoleLogin(MJGameRoleInfo roleInfo, Action onSuccess, Action<MJGameResult> onError)
        {
            ReportRoleEvent("events/role-login", roleInfo, "Role login", onSuccess, onError);
        }

        private void ReportUiStage(string eventType, string logLabel, Action onSuccess, Action<MJGameResult> onError)
        {
            var info = CollectLifecycleInfo();
            if (string.IsNullOrEmpty(info.device_id))
            {
                onError?.Invoke(MJGameResult.Fail(5001, "device_id is required"));
                return;
            }

            var body = new MJGameUiStageRequest
            {
                event_type = eventType,
                device_id = info.device_id,
                device_model = info.device_model,
                os = info.os,
                os_version = info.os_version,
                app_version = info.app_version,
                sdk_version = info.sdk_version,
                language = info.language
            };

            _http.Post<AnalyticsResponse>("events/ui-stage", body,
                _ =>
                {
                    MJGameLogger.Info("Analytics", $"{logLabel} reported: device={info.device_id}");
                    onSuccess?.Invoke();
                },
                onError);
        }

        private void ReportGameStage(
            string eventType,
            MJGameRoleInfo roleInfo,
            string logLabel,
            Action onSuccess,
            Action<MJGameResult> onError)
        {
            var info = CollectLifecycleInfo(roleInfo);
            if (string.IsNullOrEmpty(info.device_id))
            {
                onError?.Invoke(MJGameResult.Fail(5001, "device_id is required"));
                return;
            }

            var body = new MJGameGameStageRequest
            {
                event_type = eventType,
                device_id = info.device_id,
                device_model = info.device_model,
                os = info.os,
                os_version = info.os_version,
                app_version = info.app_version,
                sdk_version = info.sdk_version,
                language = info.language,
                server_id = info.server_id,
                server_name = info.server_name,
                role_id = info.role_id,
                role_name = info.role_name,
                role_level = info.role_level,
                role_class = info.role_class
            };

            _http.Post<AnalyticsResponse>("events/game-stage", body,
                _ =>
                {
                    MJGameLogger.Info("Analytics",
                        $"{logLabel} reported: server={info.server_name}, role={info.role_name}");
                    onSuccess?.Invoke();
                },
                onError);
        }

        private void ReportRoleEvent(
            string path,
            MJGameRoleInfo roleInfo,
            string logLabel,
            Action onSuccess,
            Action<MJGameResult> onError)
        {
            if (roleInfo == null)
            {
                onError?.Invoke(MJGameResult.Fail(5002, "Role info is required"));
                return;
            }

            var info = CollectLifecycleInfo(roleInfo);
            if (string.IsNullOrEmpty(info.device_id))
            {
                onError?.Invoke(MJGameResult.Fail(5001, "device_id is required"));
                return;
            }

            _http.Post<AnalyticsResponse>(path, info,
                _ =>
                {
                    MJGameLogger.Info("Analytics",
                        $"{logLabel} reported: server={info.server_name}, role={info.role_name}");
                    onSuccess?.Invoke();
                },
                onError);
        }
    }

    [Serializable]
    public class MJGameActivateInfo
    {
        public string device_id;
        public string device_model;
        public string os;
        public string os_version;
        public string app_version;
        public string sdk_version;
        public string language;
    }

    [Serializable]
    public class MJGameLifecycleInfo
    {
        public string device_id;
        public string device_model;
        public string os;
        public string os_version;
        public string app_version;
        public string sdk_version;
        public string language;
        public string server_id;
        public string server_name;
        public string role_id;
        public string role_name;
        public int role_level;
        public string role_class;
    }

    [Serializable]
    public class MJGameRoleInfo
    {
        public string server_id;
        public string server_name;
        public string role_id;
        public string role_name;
        public int role_level;
        public string role_class;
    }

    [Serializable]
    public class MJGameUiStageRequest
    {
        public string event_type;
        public string device_id;
        public string device_model;
        public string os;
        public string os_version;
        public string app_version;
        public string sdk_version;
        public string language;
    }

    [Serializable]
    public class MJGameGameStageRequest
    {
        public string event_type;
        public string device_id;
        public string device_model;
        public string os;
        public string os_version;
        public string app_version;
        public string sdk_version;
        public string language;
        public string server_id;
        public string server_name;
        public string role_id;
        public string role_name;
        public int role_level;
        public string role_class;
    }

    [Serializable]
    public class AnalyticsResponse : MJGameResponse
    {
        public AnalyticsResponseData data;
    }

    [Serializable]
    public class AnalyticsResponseData
    {
        public string event_id;
        public string role_event_id;
    }
}
