using SIGCM2.Application.Abstractions;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Common;
using SIGCM2.Domain.Exceptions;

namespace SIGCM2.Application.Usuarios.Permisos;

/// <summary>
/// UDT-009: Handles GET /api/v1/users/{id}/permisos.
/// Resolves role permissions + overrides + effective set.
/// </summary>
public sealed class GetUsuarioPermisosQueryHandler
    : ICommandHandler<GetUsuarioPermisosQuery, UsuarioPermisosDto>
{
    private readonly IUsuarioRepository _usuarioRepo;
    private readonly IRolPermisoRepository _rolPermisoRepo;

    public GetUsuarioPermisosQueryHandler(
        IUsuarioRepository usuarioRepo,
        IRolPermisoRepository rolPermisoRepo)
    {
        _usuarioRepo = usuarioRepo;
        _rolPermisoRepo = rolPermisoRepo;
    }

    public async Task<UsuarioPermisosDto> Handle(GetUsuarioPermisosQuery query)
    {
        var usuario = await _usuarioRepo.GetByIdAsync(query.Id)
            ?? throw new UsuarioNotFoundException(query.Id);

        var rolPermisoEntities = await _rolPermisoRepo.GetByRolCodigoAsync(usuario.Rol);
        var rolPermisos = rolPermisoEntities
            .Select(p => p.Codigo)
            .OrderBy(c => c, StringComparer.Ordinal)
            .ToArray();

        var overrides = PermisosOverride.FromJson(usuario.PermisosJson);

        var effective = PermisoResolver.Resolve(rolPermisos, overrides)
            .OrderBy(c => c, StringComparer.Ordinal)
            .ToArray();

        return new UsuarioPermisosDto(
            UsuarioId: usuario.Id,
            Rol: usuario.Rol,
            RolPermisos: rolPermisos,
            Grant: overrides.Grant,
            Deny: overrides.Deny,
            Effective: effective);
    }
}
