using System.Security.Authentication;
using System.Security.Claims;
using IdentityModel;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using XF.Domain.Dependency;
using XF.Domain.Extensions;

namespace XF.Domain.Authentications
{
    public class DefaultSessionContext : ISessionContext, IScopeDependency
    {
        private readonly IHttpContextAccessor _contextAccessor;
        private readonly ISessionContextProvider _sessionContextProvider;

        public DefaultSessionContext(IHttpContextAccessor httpContextAccessor, IServiceProvider serviceProvider)
        {
            _contextAccessor = httpContextAccessor;
            _sessionContextProvider = serviceProvider.GetService<ISessionContextProvider>();
            _contextAccessor.HttpContext ??= new DefaultHttpContext();
        }

        /// <summary>
        /// Id of current tenant or null for host
        /// </summary>
        public string? UserId
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
            init { }
        }

        /// <summary>
        /// Id of current user or throw Exception for guest
        /// </summary>
        /// <exception cref="AuthenticationException"></exception>
        public string RequiredUserId => UserId ?? throw new ArgumentNullException();

        public string? UserName
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.UserDisplayName);
            init { }
        }

        public string? Phone
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(JwtClaimTypes.PhoneNumber);
            init { }
        }

        /// <summary>
        /// Roles
        /// 不能使用 JwtClaimTypes.Role 来获取Role
        /// 在 JwtBearerHandler 处理 JWT 令牌时，它会使用 Microsoft.AspNetCore.Authentication.JwtBearer 自动转换 Claim 名称。
        /// </summary>
        // public string[] Roles { get => _contextAccessor.HttpContext?.User.Claims.Where(d => d.Type == JwtClaimTypes.Role).Select(d => d.Value).ToArray(); init { } }
        public string[] Roles
        {
            get => _contextAccessor.HttpContext?.User.Claims.Where(d => d.Type == ClaimTypes.Role).Select(d => d.Value).ToArray();
            init { }
        }

        public string? OrgId
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentId);
            init { }
        }

        public string? OrgName
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentName);
            init { }
        }

        public int OrgLevel
        {
            get => _contextAccessor.HttpContext?.User.FindIntValue(AppClaimTypes.DepartmentLevel) ?? 0;
            init { }
        }

        public string? OrgAreaCode
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentAreaCode);
            init { }
        }

        public bool OrgIsCenter
        {
            get => _contextAccessor.HttpContext?.User.FindBoolValue(AppClaimTypes.DepartmentIsCenter) ?? false;
            init { }
        }

        /// <summary>
        /// 部门行政区划名称
        /// </summary>
        public string? OrgAreaName
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentAreaName);
            init { }
        }

        public string? AreaId
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.AreaId);
            init { }
        }

        public string RequiredOrgId => OrgId ?? throw new ArgumentNullException();

        public string? ClientId
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(JwtClaimTypes.ClientId);
            init { }
        }

        /// <summary>
        /// 工号
        /// </summary>
        public string? StaffNo
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.StaffNo);
            init { }
        }

        /// <summary>
        /// 第三方平台用户唯一标识
        /// 例如: 微信的OpenId
        /// </summary>
        public string? OpenId
        {
            get => _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.OpenId);
            init { }
        }

    }

    public static class ClaimsPrincipalExtensions
    {
        public static int FindIntValue(this ClaimsPrincipal claims, string claimType)
        {
            var value = claims.FindFirstValue(claimType);
            return int.TryParse(value, out int result) ? result : default;
        }

        public static bool FindBoolValue(this ClaimsPrincipal claims, string claimType)
        {
            var value = claims.FindFirstValue(claimType);
            return bool.TryParse(value, out bool result) ? result : default;
        }
    }
}