using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 获取租户角色权限列表查询处理器。
/// </summary>
public sealed class GetTenantRolePermissionsQueryHandler(
    IRoleRepository roleRepository,
    IRolePermissionRepository rolePermissionRepository,
    IPermissionRepository permissionRepository)
    : IRequestHandler<GetTenantRolePermissionsQuery, IReadOnlyList<PermissionDto>>
{
    /// <inheritdoc />
    public async Task<IReadOnlyList<PermissionDto>> Handle(GetTenantRolePermissionsQuery request, CancellationToken cancellationToken)
    {
        // 1. 校验角色存在
        var role = await roleRepository.FindByIdAsync(PortalType.Tenant, request.TenantId, request.RoleId, cancellationToken)
            ?? throw new BusinessException(ErrorCodes.NotFound, "角色不存在");

        // 2. 查询角色权限关系
        var rolePermissions = await rolePermissionRepository.GetByRoleIdsAsync(
            PortalType.Tenant,
            request.TenantId,
            [request.RoleId],
            cancellationToken);

        // 3. 提取权限 ID 集合
        var permissionIds = rolePermissions.Select(rp => rp.PermissionId).Distinct().ToArray();
        if (permissionIds.Length == 0)
        {
            return [];
        }

        // 4. 查询权限详情
        var permissions = await permissionRepository.GetByIdsAsync(permissionIds, cancellationToken);

        // 5. 映射 DTO
        return permissions
            .Select(p => new PermissionDto
            {
                Portal = p.Portal,
                Id = p.Id,
                ParentId = p.ParentId,
                SortOrder = p.SortOrder,
                Type = p.Type,
                Name = p.Name,
                Code = p.Code,
                Description = p.Description
            })
            .ToArray();
    }
}
