using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Domain.Identity;

namespace SolutionErp.Api.Authorization;

public class MenuPermissionHandler(
    IApplicationDbContext db,
    UserManager<User> userManager,
    RoleManager<Role> roleManager) : AuthorizationHandler<MenuPermissionRequirement>
{
    protected override async Task HandleRequirementAsync(
        AuthorizationHandlerContext context, MenuPermissionRequirement req)
    {
        var sub = context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
               ?? context.User.FindFirst("sub")?.Value;
        if (!Guid.TryParse(sub, out var userId)) return;

        var user = await userManager.FindByIdAsync(userId.ToString());
        if (user is null || !user.IsActive) return;

        var roleNames = await userManager.GetRolesAsync(user);

        // Admin bypass
        if (roleNames.Contains(AppRoles.Admin))
        {
            context.Succeed(req);
            return;
        }

        var roleIds = new List<Guid>();
        foreach (var name in roleNames)
        {
            var r = await roleManager.FindByNameAsync(name);
            if (r is not null) roleIds.Add(r.Id);
        }

        var baseQuery = db.Permissions
            .Where(p => roleIds.Contains(p.RoleId) && p.MenuKey == req.MenuKey);

        var hasPermission = req.Action switch
        {
            "Read" => await baseQuery.AnyAsync(p => p.CanRead),
            "Create" => await baseQuery.AnyAsync(p => p.CanCreate),
            "Update" => await baseQuery.AnyAsync(p => p.CanUpdate),
            "Delete" => await baseQuery.AnyAsync(p => p.CanDelete),
            _ => false,
        };

        if (hasPermission) context.Succeed(req);
    }
}
