using Hotline.Identity.Accounts;
using Hotline.Settings;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Tools;
using Hotline.Users;
using IdentityModel;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;
using XF.Domain.Authentications;
using XF.Domain.Repository;
using static Hotline.AppDefaults;

namespace Hotline.Api.Filter;

public class StaffNoSessionContextFilter : ActionFilterAttribute
{
    private IAccountRepository _accountRepository;
    private IRepository<User> _userRepository;

    public StaffNoSessionContextFilter()
    {
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        await ReloadUser(context);
        await next();
    }

    private async Task ReloadUser(ActionExecutingContext context)
    {
        try
        {
            _accountRepository = context.HttpContext.RequestServices.GetRequiredService<IAccountRepository>();
            _userRepository = context.HttpContext.RequestServices.GetRequiredService<IRepository<User>>();
            var notifyInDto = context.ActionArguments.Values.FirstOrDefault() as NotifyInDto;
            if (notifyInDto == null) return;
            var user = _userRepository.Queryable().Where(m => m.StaffNo == notifyInDto.StaffNo).First();
            if (user == null) return;
            var account = await _accountRepository.GetExtAsync(m => m.Id == user.Id, m => m.Includes(x => x.Roles));

            List<Claim> userClaims = [
                new(JwtClaimTypes.Subject, account.Id),
                new(JwtClaimTypes.PhoneNumber, account.PhoneNo ?? string.Empty),
                new(ClaimTypes.NameIdentifier, user.Id),
                new(AppClaimTypes.UserDisplayName, account.Name),
                new(AppClaimTypes.DepartmentId, user.OrgId ?? string.Empty),
                new(AppClaimTypes.DepartmentIsCenter, user.Organization?.IsCenter.ToString() ?? string.Empty),
                new(AppClaimTypes.DepartmentName, user.Organization?.Name ?? string.Empty),
                new(AppClaimTypes.DepartmentAreaCode, user.Organization?.AreaCode ?? string.Empty),
                new(AppClaimTypes.DepartmentAreaName, user.Organization?.AreaName ?? string.Empty),
                new(AppClaimTypes.DepartmentLevel, user.Organization?.Level.ToString() ?? string.Empty),
                new(AppClaimTypes.AreaId, user.OrgId?.GetHigherOrgId() ?? string.Empty),
            ];
            userClaims.AddRange(account.Roles.Select(d => new Claim(JwtClaimTypes.Role, d.Name)));
            context.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(userClaims));
        }
        catch
        {
        }
    }
}
