import { useAuthStore } from "@/lib/stores/auth.store";
import type { NavItemKey } from "@/lib/sidebar-nav";

/**
 * Client mirror of the backend `Meezi.Core.Authorization.Permission` enum. The
 * server (EnsurePermission) remains the single source of truth — these values
 * only drive what the UI *shows* (pages, action buttons). Never rely on them
 * for actual security. Keep this list in sync with Permission.cs.
 */
export type Permission =
  // Café administration
  | "ViewCafeSettings"
  | "ManageCafeSettings"
  | "ManageDiscoverProfile"
  | "ViewBilling"
  | "ManageBilling"
  | "ViewBranches"
  | "CreateBranch"
  | "EditBranch"
  | "DeleteBranch"
  | "ManageRoles"
  | "ViewPrintSettings"
  | "ManagePrintSettings"
  // Taxes
  | "ViewTaxes"
  | "CreateTax"
  | "EditTax"
  | "DeleteTax"
  // Staff & HR
  | "ViewStaff"
  | "CreateStaff"
  | "EditStaff"
  | "DeleteStaff"
  | "ManageStaff"
  | "ManageStaffCredentials"
  | "ViewAttendance"
  | "ManageAttendance"
  | "ViewSchedules"
  | "ManageSchedules"
  | "ViewLeave"
  | "ReviewLeave"
  | "ViewSalaries"
  | "ManageSalaries"
  // Menu
  | "ViewMenu"
  | "CreateMenuItem"
  | "EditMenuItem"
  | "DeleteMenuItem"
  // Inventory
  | "ViewInventory"
  | "CreateInventory"
  | "EditInventory"
  | "DeleteInventory"
  // Tables
  | "ViewTables"
  | "ManageTables"
  // Reservations
  | "ViewReservations"
  | "CreateReservation"
  | "EditReservation"
  | "DeleteReservation"
  // Orders & POS
  | "ViewOrders"
  | "ProcessOrders"
  | "EditOrder"
  | "VoidOrder"
  | "RefundOrder"
  | "ApplyDiscount"
  | "CompOrder"
  | "HandlePayments"
  | "UpdateOrderStatus"
  // Register / cash
  | "OperateRegister"
  | "OpenCashDrawer"
  // Queue
  | "ViewQueue"
  | "ManageQueue"
  // Kitchen
  | "ViewKitchen"
  | "ManageKitchenStations"
  // Delivery
  | "ViewDelivery"
  | "HandleDelivery"
  | "AssignDelivery"
  // Customers / CRM
  | "ViewCustomers"
  | "CreateCustomer"
  | "EditCustomer"
  | "DeleteCustomer"
  // Coupons
  | "ViewCoupons"
  | "CreateCoupon"
  | "EditCoupon"
  | "DeleteCoupon"
  // SMS / marketing
  | "ViewSms"
  | "SendSms"
  | "ManageSmsSettings"
  // Reviews
  | "ViewReviews"
  | "ManageReviews"
  // Reports & finance
  | "ViewReports"
  | "ExportReports"
  | "ViewAuditLog"
  | "ViewFinancials"
  | "ManageFinancials"
  // Expenses
  | "ViewExpenses"
  | "CreateExpense"
  | "EditExpense"
  | "DeleteExpense";

/**
 * Permission a nav page requires to be visible. Each maps to the page's "View"
 * capability. Pages not listed fall back to the owner-only / branch-account
 * visibility logic in {@link file://./auth-permissions.ts}.
 */
export const NAV_REQUIRED_PERMISSION: Partial<Record<NavItemKey, Permission>> = {
  pos: "ProcessOrders",
  tables: "ViewTables",
  queue: "ViewQueue",
  kds: "ViewKitchen",
  reservations: "ViewReservations",
  menu: "ViewMenu",
  orders: "ViewOrders",
  reports: "ViewReports",
  crm: "ViewCustomers",
  coupons: "ViewCoupons",
  sms: "ViewSms",
  reviews: "ViewReviews",
  inventory: "ViewInventory",
  expenses: "ViewExpenses",
  shifts: "OperateRegister",
  taxes: "ViewTaxes",
  hr: "ViewStaff",
  branches: "ViewBranches",
  subscription: "ViewBilling",
};

/** Read the effective permission set off an auth response (null = legacy session). */
export function permissionsOf(
  user: { permissions?: string[] | null } | null | undefined
): Set<string> | null {
  if (!user?.permissions) return null;
  return new Set(user.permissions);
}

/**
 * Whether the user holds a capability. Legacy sessions (no permissions array, e.g.
 * issued before this feature shipped) return `true` so the UI degrades gracefully
 * until the next token refresh — the server still enforces real access.
 */
export function hasPermission(
  user: { permissions?: string[] | null } | null | undefined,
  permission: Permission
): boolean {
  const set = permissionsOf(user);
  if (set === null) return true;
  return set.has(permission);
}

/** React hook: does the current user hold the given permission? */
export function useHasPermission(permission: Permission): boolean {
  const user = useAuthStore((s) => s.user);
  return hasPermission(user, permission);
}
