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;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 获取用户详情处理器。
/// </summary>
public sealed class GetIdentityUserDetailQueryHandler(
    IIdentityUserRepository identityUserRepository,
    IUserRoleRepository userRoleRepository,
    IRoleRepository roleRepository,
    IRolePermissionRepository rolePermissionRepository,
    IPermissionRepository permissionRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<GetIdentityUserDetailQuery, UserDetailDto?>
{
    /// <inheritdoc />
    public async Task<UserDetailDto?> Handle(GetIdentityUserDetailQuery request, CancellationToken cancellationToken)
    {
        // 1. 获取当前租户
        var currentTenantId = tenantProvider.GetCurrentTenantId();

        // 2. 查询用户实体
        IdentityUser? user;
        if (request.IncludeDeleted)
        {
            user = await identityUserRepository.GetForUpdateIncludingDeletedAsync(currentTenantId, request.UserId, cancellationToken);
        }
        else
        {
            user = await identityUserRepository.GetForUpdateAsync(request.UserId, cancellationToken);
        }

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

        if (user.TenantId != currentTenantId)
        {
            return null;
        }

        // 3. 加载角色与权限
        var roleRelations = await userRoleRepository.GetByUserIdAsync(user.TenantId, user.Id, cancellationToken);
        var roleIds = roleRelations.Select(x => x.RoleId).Distinct().ToArray();
        var roles = roleIds.Length == 0
            ? Array.Empty<Role>()
            : await roleRepository.GetByIdsAsync(user.TenantId, 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(user.TenantId, roleIds, cancellationToken))
                .Select(x => x.PermissionId)
                .Distinct()
                .ToArray();
        var permissions = permissionIds.Length == 0
            ? Array.Empty<string>()
            : (await permissionRepository.GetByIdsAsync(user.TenantId, permissionIds, cancellationToken))
                .Select(x => x.Code)
                .Where(code => !string.IsNullOrWhiteSpace(code))
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToArray();

        // 4. 组装详情 DTO
        var now = DateTime.UtcNow;
        return new UserDetailDto
        {
            UserId = user.Id,
            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
        };
    }
}
