using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Domain.Identity.Repositories;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 获取用户详情处理器。
/// </summary>
public sealed class GetIdentityUserDetailQueryHandler(
    IIdentityUserRepository identityUserRepository,
    IUserRoleRepository userRoleRepository,
    IRoleRepository roleRepository,
    IRolePermissionRepository rolePermissionRepository,
    IPermissionRepository permissionRepository)
    : IRequestHandler<GetIdentityUserDetailQuery, UserDetailDto?>
{
    /// <inheritdoc />
    public async Task<UserDetailDto?> Handle(GetIdentityUserDetailQuery request, CancellationToken cancellationToken)
    {
        // 1. 查询用户实体
        var user = request.IncludeDeleted
            ? await identityUserRepository.GetForUpdateIncludingDeletedAsync(request.UserId, cancellationToken)
            : await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken);

        if (user == null)
        {
            return null;
        }

        // 2. (空行后) 限定仅允许查看平台管理员账号
        if (user.Portal != PortalType.Admin || user.TenantId is not null)
        {
            return null;
        }

        // 3. (空行后) 加载角色与权限
        var portal = PortalType.Admin;

        // 4. 查询用户角色关系
        var roleRelations = await userRoleRepository.GetByUserIdAsync(portal, null, user.Id, cancellationToken);
        var roleIds = roleRelations.Select(x => x.RoleId).Distinct().ToArray();
        var roles = roleIds.Length == 0
            ? Array.Empty<Role>()
            : await roleRepository.GetByIdsAsync(portal, null, roleIds, cancellationToken);
        var roleCodes = roles.Select(x => x.Code)
            .Where(code => !string.IsNullOrWhiteSpace(code))
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToArray();
        var permissionIds = roleIds.Length == 0
            ? Array.Empty<long>()
            : (await rolePermissionRepository.GetByRoleIdsAsync(portal, null, roleIds, cancellationToken))
                .Select(x => x.PermissionId)
                .Distinct()
                .ToArray();
        var permissions = permissionIds.Length == 0
            ? Array.Empty<string>()
            : (await permissionRepository.GetByIdsAsync(permissionIds, cancellationToken))
                .Select(x => x.Code)
                .Where(code => !string.IsNullOrWhiteSpace(code))
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToArray();

        // 5. 组装详情 DTO
        var now = DateTime.UtcNow;
        return new UserDetailDto
        {
            UserId = user.Id,
            Portal = user.Portal,
            TenantId = user.TenantId,
            MerchantId = user.MerchantId,
            Account = user.Account,
            DisplayName = user.DisplayName,
            Phone = user.Phone,
            Email = user.Email,
            Status = user.Status,
            IsLocked = user.Status == IdentityUserStatus.Locked || (user.LockedUntil.HasValue && user.LockedUntil.Value > now),
            Roles = roleCodes,
            RoleIds = roleIds.Select(id => id.ToString()).ToArray(),
            Permissions = permissions,
            CreatedAt = user.CreatedAt,
            LastLoginAt = user.LastLoginAt,
            Avatar = user.Avatar,
            RowVersion = user.RowVersion
        };
    }
}
