using System;
using System.Security.Cryptography;
using System.Text;

namespace MJGameSDK
{
    /// <summary>
    /// 登录会话：access/refresh/request_key（仅内存，进程内有效）。
    /// </summary>
    public static class MJGameAuthSession
    {
        public static string AccessToken { get; private set; }
        public static string RefreshToken { get; private set; }
        public static string RequestKey { get; private set; }
        public static DateTime AccessExpiresAtUtc { get; private set; }
        public static DateTime RequestKeyExpiresAtUtc { get; private set; }

        public static bool HasAccessToken => !string.IsNullOrEmpty(AccessToken);
        public static bool HasRequestKey => !string.IsNullOrEmpty(RequestKey);

        public static void ApplyLogin(
            string accessToken,
            string refreshToken,
            int expiresInSeconds,
            string requestKey,
            int requestKeyExpiresInSeconds)
        {
            AccessToken = accessToken;
            RefreshToken = refreshToken;
            RequestKey = requestKey;
            var now = DateTime.UtcNow;
            AccessExpiresAtUtc = now.AddSeconds(Math.Max(60, expiresInSeconds));
            RequestKeyExpiresAtUtc = now.AddSeconds(Math.Max(60, requestKeyExpiresInSeconds > 0 ? requestKeyExpiresInSeconds : expiresInSeconds));
        }

        public static void ApplyRefresh(string accessToken, int expiresInSeconds, string requestKey, int requestKeyExpiresInSeconds)
        {
            AccessToken = accessToken;
            if (!string.IsNullOrEmpty(requestKey))
                RequestKey = requestKey;
            var now = DateTime.UtcNow;
            AccessExpiresAtUtc = now.AddSeconds(Math.Max(60, expiresInSeconds));
            if (requestKeyExpiresInSeconds > 0)
                RequestKeyExpiresAtUtc = now.AddSeconds(Math.Max(60, requestKeyExpiresInSeconds));
            else if (!string.IsNullOrEmpty(requestKey))
                RequestKeyExpiresAtUtc = AccessExpiresAtUtc;
        }

        public static void Clear()
        {
            AccessToken = null;
            RefreshToken = null;
            RequestKey = null;
            AccessExpiresAtUtc = DateTime.MinValue;
            RequestKeyExpiresAtUtc = DateTime.MinValue;
        }

        /// <summary>剩余不足 bufferSeconds 或已过期则需要续期。</summary>
        public static bool NeedsRefresh(int bufferSeconds = 300)
        {
            if (!HasAccessToken)
                return false;
            var deadline = DateTime.UtcNow.AddSeconds(bufferSeconds);
            return AccessExpiresAtUtc <= deadline || !HasRequestKey || RequestKeyExpiresAtUtc <= deadline;
        }

        public static string BuildSignRaw(string method, string path, string timestamp, string nonce, string body)
        {
            method = (method ?? "GET").ToUpperInvariant();
            path = (path ?? "").TrimStart('/');
            body = body ?? "";
            return method + "\n" + path + "\n" + timestamp + "\n" + nonce + "\n" + body;
        }

        public static string SignHmacSha256(string raw, string requestKey)
        {
            using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(requestKey ?? "")))
            {
                var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(raw ?? ""));
                var sb = new StringBuilder(hash.Length * 2);
                for (var i = 0; i < hash.Length; i++)
                    sb.Append(hash[i].ToString("x2"));
                return sb.ToString();
            }
        }

        public static string NewNonce()
        {
            return Guid.NewGuid().ToString("N");
        }
    }
}
