using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 租户用户权限分页查询处理器。
/// </summary>
public sealed class SearchUserPermissionsQueryHandler(
    IIdentityUserRepository identityUserRepository,
    IUserRoleRepository userRoleRepository,
    IRoleRepository roleRepository,
    IPermissionRepository permissionRepository,
    IRolePermissionRepository rolePermissionRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<SearchUserPermissionsQuery, PagedResult<UserPermissionDto>>
{
    /// <inheritdoc />
    public async Task<PagedResult<UserPermissionDto>> Handle(SearchUserPermissionsQuery request, CancellationToken cancellationToken)
    {
        // 1. 获取租户并查询用户
        var tenantId = tenantProvider.GetCurrentTenantId();
        var users = await identityUserRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);

        // 2. 排序与分页
        var sorted = SortUsers(users, request.SortBy, request.SortDescending);
        var paged = sorted
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .ToList();

        // 3. 解析角色与权限
        var resolved = await ResolveRolesAndPermissionsAsync(tenantId, paged, cancellationToken);
        var items = paged.Select(user => new UserPermissionDto
        {
            UserId = user.Id,
            TenantId = user.TenantId,
            MerchantId = user.MerchantId,
            Account = user.Account,
            DisplayName = user.DisplayName,
            Roles = resolved[user.Id].roles,
            Permissions = resolved[user.Id].permissions,
            CreatedAt = user.CreatedAt
        }).ToList();

        return new PagedResult<UserPermissionDto>(items, request.Page, request.PageSize, users.Count);
    }

    private static IOrderedEnumerable<Domain.Identity.Entities.IdentityUser> SortUsers(
        IReadOnlyCollection<Domain.Identity.Entities.IdentityUser> users,
        string? sortBy,
        bool sortDescending)
    {
        return sortBy?.ToLowerInvariant() switch
        {
            "account" => sortDescending
                ? users.OrderByDescending(x => x.Account)
                : users.OrderBy(x => x.Account),
            "displayname" => sortDescending
                ? users.OrderByDescending(x => x.DisplayName)
                : users.OrderBy(x => x.DisplayName),
            _ => sortDescending
                ? users.OrderByDescending(x => x.CreatedAt)
                : users.OrderBy(x => x.CreatedAt)
        };
    }

    private async Task<Dictionary<long, (string[] roles, string[] permissions)>> ResolveRolesAndPermissionsAsync(
        long tenantId,
        IReadOnlyCollection<Domain.Identity.Entities.IdentityUser> users,
        CancellationToken cancellationToken)
    {
        // 1. 查询用户角色关系
        var userIds = users.Select(x => x.Id).ToArray();
        var userRoleRelations = await userRoleRepository.GetByUserIdsAsync(tenantId, userIds, cancellationToken);
        var roleIds = userRoleRelations.Select(x => x.RoleId).Distinct().ToArray();

        // 2. 查询角色信息
        var roles = roleIds.Length == 0
            ? Array.Empty<Domain.Identity.Entities.Role>()
            : await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken);
        var roleCodeMap = roles.ToDictionary(r => r.Id, r => r.Code, comparer: EqualityComparer<long>.Default);

        // 3. 查询角色-权限关系
        var rolePermissions = roleIds.Length == 0
            ? Array.Empty<Domain.Identity.Entities.RolePermission>()
            : await rolePermissionRepository.GetByRoleIdsAsync(tenantId, roleIds, cancellationToken);
        var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray();

        // 4. 查询权限详情
        var permissions = permissionIds.Length == 0
            ? Array.Empty<Domain.Identity.Entities.Permission>()
            : await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken);
        var permissionCodeMap = permissions.ToDictionary(p => p.Id, p => p.Code, comparer: EqualityComparer<long>.Default);

        var rolePermissionsLookup = rolePermissions
            .GroupBy(rp => rp.RoleId)
            .ToDictionary(g => g.Key, g => g.Select(rp => rp.PermissionId).ToArray(), comparer: EqualityComparer<long>.Default);

        var result = new Dictionary<long, (string[] roles, string[] permissions)>();
        foreach (var userId in userIds)
        {
            // 5. 聚合用户角色与权限编码
            var rolesForUser = userRoleRelations.Where(ur => ur.UserId == userId).Select(ur => ur.RoleId).Distinct().ToArray();
            var roleCodes = rolesForUser
                .Select(rid => roleCodeMap.GetValueOrDefault(rid))
                .Where(c => !string.IsNullOrWhiteSpace(c))
                .Select(c => c!)
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToArray();

            var permissionCodes = rolesForUser
                .SelectMany(rid => rolePermissionsLookup.GetValueOrDefault(rid) ?? Array.Empty<long>())
                .Select(pid => permissionCodeMap.GetValueOrDefault(pid))
                .Where(code => !string.IsNullOrWhiteSpace(code))
                .Select(code => code!)
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToArray();

            result[userId] = (roleCodes, permissionCodes);
        }

        return result;
    }
}
