#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
#if UNITY_EDITOR
using UnityEditor;
#endif
using IGP.UnitySDK.Abstractions;
using IGP.UnitySDK.Models;
using IGP.UnitySDK.Core;
using IGP.UnitySDK.Network;
using IGP.UnitySDK.Protocol;

namespace IGP.UnitySDK
{
    public partial class IGPRuntimeManager
    {

        /// <summary>
        /// 上报一次性成就解锁事件。
        /// </summary>
        public async Task<AchievementReportResult> UnlockAchievementAsync(
            string achievementKey,
            string? eventId = null,
            long? occurredAtUnixMs = null,
            int? appId = null)
        {
            var session = await EnsureDesktopSessionAsync(appId);
            EnsureDesktopUserContextAvailable();
            EnsureDesktopCapability(
                currentDesktopCapabilities?.achievements ?? false,
                "Achievements are not available on the current desktop session");
            var result = await session.UnlockAchievementAsync(
                achievementKey,
                ResolveAchievementEventId(eventId),
                occurredAtUnixMs,
                appId,
                RuntimeCancellationToken);
            return ParseDesktopCommandPayload(
                result,
                () => new AchievementReportResult
                {
                    success = true,
                    message = result.Message ?? string.Empty,
                });
        }

        /// <summary>
        /// 上报进度型成就当前进度。
        /// </summary>
        public async Task<AchievementReportResult> ReportAchievementProgressAsync(
            string achievementKey,
            double progressValue,
            string? progressSourceKey = null,
            string? eventId = null,
            long? occurredAtUnixMs = null,
            int? appId = null,
            ProgressValueMode? progressValueMode = null)
        {
            return await ReportAchievementProgressCoreAsync(
                achievementKey,
                progressValue,
                progressSourceKey,
                progressValueMode,
                eventId,
                occurredAtUnixMs,
                appId);
        }

        public async Task<AchievementReportResult> ReportAchievementProgressAsync(
            string achievementKey,
            double progressValue,
            string? progressSourceKey,
            ProgressValueMode progressValueMode,
            string? eventId = null,
            long? occurredAtUnixMs = null,
            int? appId = null)
        {
            return await ReportAchievementProgressCoreAsync(
                achievementKey,
                progressValue,
                progressSourceKey,
                progressValueMode,
                eventId,
                occurredAtUnixMs,
                appId);
        }

        private async Task<AchievementReportResult> ReportAchievementProgressCoreAsync(
            string achievementKey,
            double progressValue,
            string? progressSourceKey,
            ProgressValueMode? progressValueMode,
            string? eventId,
            long? occurredAtUnixMs,
            int? appId)
        {
            var session = await EnsureDesktopSessionAsync(appId);
            EnsureDesktopUserContextAvailable();
            EnsureDesktopCapability(
                currentDesktopCapabilities?.achievements ?? false,
                "Achievements are not available on the current desktop session");
            var resolvedEventId = ResolveAchievementEventId(eventId);
            var result = progressValueMode.HasValue
                ? await session.ReportAchievementProgressAsync(
                    achievementKey,
                    progressValue,
                    progressSourceKey,
                    progressValueMode.Value,
                    resolvedEventId,
                    occurredAtUnixMs,
                    appId,
                    RuntimeCancellationToken)
                : await session.ReportAchievementProgressAsync(
                    achievementKey,
                    progressValue,
                    progressSourceKey,
                    resolvedEventId,
                    occurredAtUnixMs,
                    appId,
                    RuntimeCancellationToken);
            return ParseDesktopCommandPayload(
                result,
                () => new AchievementReportResult
                {
                    success = true,
                    message = result.Message ?? string.Empty,
                });
        }

        private static string ResolveAchievementEventId(string? eventId)
        {
            return string.IsNullOrWhiteSpace(eventId)
                ? Guid.NewGuid().ToString("N")
                : eventId;
        }

        /// <summary>
        /// 清除当前游戏的全部成就。
        /// </summary>
        public async Task<AchievementClearResult> ClearAchievementsAsync(int? appId = null)
        {
            var session = await EnsureDesktopSessionAsync(appId);
            EnsureDesktopUserContextAvailable();
            EnsureDesktopCapability(
                currentDesktopCapabilities?.achievements ?? false,
                "Achievements are not available on the current desktop session");
            var result = await session.ClearAchievementsAsync(appId, RuntimeCancellationToken);
            return ParseDesktopCommandPayload(
                result,
                () => new AchievementClearResult
                {
                    success = true,
                    message = result.Message ?? string.Empty,
                });
        }
    }
}
