#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;
#if UNITY_EDITOR
using UnityEditor;
#endif
using IGP.UnitySDK.Abstractions;
using IGP.UnitySDK.Models;

namespace IGP.UnitySDK
{
    public partial class IGPRuntimeManager
    {

        public async Task<IGPAntiAddictionStatus> RefreshAntiAddictionStatusAsync(int? appIdOverride = null)
        {
            var appId = ResolveHostAppId(appIdOverride);
            if (!appId.HasValue)
            {
                throw new IGPSDKException("IGP appId is required", IGPErrorCodes.ERR_APP_ID_REQUIRED);
            }

            var session = await EnsureHostSessionAsync(appId.Value);
            var status = await session.GetDesktopAntiAddictionStatusAsync(RuntimeCancellationToken);
            ApplyAntiAddictionStatus(status);
            return status;
        }

        public async Task<IGPAntiAddictionRealNameWebSession> CreateAntiAddictionRealNameWebSessionAsync(int? appIdOverride = null)
        {
            var appId = ResolveHostAppId(appIdOverride);
            if (!appId.HasValue)
            {
                throw new IGPSDKException("IGP appId is required", IGPErrorCodes.ERR_APP_ID_REQUIRED);
            }

            var session = await EnsureHostSessionAsync(appId.Value);
            return await session.CreateDesktopAntiAddictionRealNameUrlAsync(
                appId.Value,
                RuntimeCancellationToken);
        }

        public async Task<IGPAntiAddictionAccountSummary> SubmitAntiAddictionRealNameAsync(
            string realName,
            string idCardNumber,
            string identityDocumentType = IGPAntiAddictionIdentityDocumentTypes.CnIdCard,
            int? appIdOverride = null)
        {
            if (string.IsNullOrWhiteSpace(realName))
            {
                throw new ArgumentException("Real name is required", nameof(realName));
            }

            if (string.IsNullOrWhiteSpace(idCardNumber))
            {
                throw new ArgumentException("Identity document number is required", nameof(idCardNumber));
            }

            if (string.IsNullOrWhiteSpace(identityDocumentType))
            {
                throw new ArgumentException("Identity document type is required", nameof(identityDocumentType));
            }

            var appId = ResolveHostAppId(appIdOverride);
            if (!appId.HasValue)
            {
                throw new IGPSDKException("IGP appId is required", IGPErrorCodes.ERR_APP_ID_REQUIRED);
            }

            var session = await EnsureHostSessionAsync(appId.Value);
            var profile = await session.SubmitDesktopAntiAddictionRealNameAsync(
                realName,
                idCardNumber,
                identityDocumentType,
                RuntimeCancellationToken);
            await RefreshAntiAddictionStatusAsync(appId.Value);
            return profile;
        }

        private void HandleDesktopAntiAddictionChanged(IGPAntiAddictionStatus status)
        {
            ApplyAntiAddictionStatus(status);
        }

        private void ApplyAntiAddictionStatus(IGPAntiAddictionStatus status)
        {
            if (status == null)
            {
                return;
            }

            var previous = currentAntiAddictionStatus;
            currentAntiAddictionStatus = status;
            if (!isDestroyed && !AntiAddictionStatusEquals(previous, status))
            {
                AntiAddictionChanged?.Invoke(status);
            }
        }

        private static bool AntiAddictionStatusEquals(
            IGPAntiAddictionStatus? left,
            IGPAntiAddictionStatus right)
        {
            return left != null &&
                left.enabled == right.enabled &&
                left.canPlayNow == right.canPlayNow &&
                string.Equals(left.state, right.state, StringComparison.Ordinal) &&
                string.Equals(left.reasonCode, right.reasonCode, StringComparison.Ordinal) &&
                string.Equals(left.reasonMessage, right.reasonMessage, StringComparison.Ordinal) &&
                left.isMinor == right.isMinor &&
                string.Equals(left.ageBand, right.ageBand, StringComparison.Ordinal) &&
                string.Equals(left.evaluatedAt, right.evaluatedAt, StringComparison.Ordinal) &&
                string.Equals(left.playableUntil, right.playableUntil, StringComparison.Ordinal) &&
                string.Equals(left.nextPlayableAt, right.nextPlayableAt, StringComparison.Ordinal) &&
                string.Equals(left.nextStatusChangeAt, right.nextStatusChangeAt, StringComparison.Ordinal);
        }
    }
}
