using Meezi.Core.Enums;

namespace Meezi.Core.Authorization;

/// <summary>
/// The authoritative role→capability matrix. Change what a role can do here and
/// every controller that calls <c>EnsurePermission</c> updates automatically.
/// </summary>
public static class RolePermissions
{
    private static readonly IReadOnlyDictionary<EmployeeRole, HashSet<Permission>> Matrix =
        new Dictionary<EmployeeRole, HashSet<Permission>>
        {
            [EmployeeRole.Owner] = AllPermissions(),

            [EmployeeRole.Manager] = new()
            {
                Permission.ManageStaff,
                Permission.ManageMenu,
                Permission.ManageInventory,
                Permission.ManageExpenses,
                Permission.ManageTaxes,
                Permission.ManageCoupons,
                Permission.ManageReservations,
                Permission.ManageTables,
                Permission.ViewReports,
                Permission.ReviewLeave,
                Permission.ManageSalaries,
                Permission.ManagePrintSettings,
                Permission.ProcessOrders,
                Permission.HandlePayments,
                Permission.OperateRegister,
                Permission.ManageQueue,
                Permission.ViewKitchen,
                Permission.HandleDelivery,
            },

            [EmployeeRole.Cashier] = new()
            {
                Permission.ProcessOrders,
                Permission.HandlePayments,
                Permission.OperateRegister,
                Permission.ManageQueue,
                Permission.ManageReservations,
            },

            [EmployeeRole.Waiter] = new()
            {
                Permission.ProcessOrders,
                Permission.ManageReservations,
                Permission.ManageQueue,
            },

            [EmployeeRole.Chef] = new()
            {
                Permission.ViewKitchen,
            },

            [EmployeeRole.Delivery] = new()
            {
                Permission.HandleDelivery,
            },
        };

    public static bool Has(EmployeeRole role, Permission permission) =>
        Matrix.TryGetValue(role, out var set) && set.Contains(permission);

    public static IReadOnlySet<Permission> For(EmployeeRole role) =>
        Matrix.TryGetValue(role, out var set) ? set : new HashSet<Permission>();

    /// <summary>True for roles that administer the whole café across all branches.</summary>
    public static bool IsCafeWide(EmployeeRole role) => role == EmployeeRole.Owner;

    private static HashSet<Permission> AllPermissions() =>
        new(Enum.GetValues<Permission>());
}
