import type { AuthUser } from "@/auth/types";
import type { RuleEngineResourceSlug } from "@/types/rule-engine";

export const FREIGHT_PERMS = {
  overview: {
    view: "edr_freight_app:overview:view",
  },
  support: {
    view: "edr_freight_app:support:view",
  },
  bookings: {
    view: "edr_freight_app:bookings:view",
    create: "edr_freight_app:bookings:create",
    clearanceView: "edr_freight_app:bookings:clearance_view",
    staffAccept: "edr_freight_app:bookings:staff_accept",
    requestChanges: "edr_freight_app:bookings:request_changes",
    reject: "edr_freight_app:bookings:reject",
    approveLineStaff: "edr_freight_app:bookings:approve_line_staff",
    approveDirector: "edr_freight_app:bookings:approve_director",
    approveCeo: "edr_freight_app:bookings:approve_ceo",
    rejectApproval: "edr_freight_app:bookings:reject_approval",
    generateContract: "edr_freight_app:bookings:generate_contract",
    signStaff: "edr_freight_app:bookings:sign_staff",
    operations: "edr_freight_app:bookings:operations",
    cancel: "edr_freight_app:bookings:cancel",
    reviewDocuments: "edr_freight_app:bookings:review_documents",
    uploadClearanceOutput: "edr_freight_app:bookings:upload_clearance_output",
    finalizeClearance: "edr_freight_app:bookings:finalize_clearance",
    docReviewAlert: "edr_freight_app:bookings:doc_review_alert",
  },
  contracts: {
    view: "edr_freight_app:contracts:view",
    // Intake actions are split per freight type — mirror of the API registry.
    staffAccept: {
      bulk: "edr_freight_app:contracts:staff_accept:bulk",
      container: "edr_freight_app:contracts:staff_accept:container",
    },
    requestChanges: {
      bulk: "edr_freight_app:contracts:request_changes:bulk",
      container: "edr_freight_app:contracts:request_changes:container",
    },
    reject: {
      bulk: "edr_freight_app:contracts:reject:bulk",
      container: "edr_freight_app:contracts:reject:container",
    },
    approveLineStaff: "edr_freight_app:contracts:approve_line_staff",
    approveDirector: "edr_freight_app:contracts:approve_director",
    approveCeo: "edr_freight_app:contracts:approve_ceo",
    hazardousApprovalOne: "edr_freight_app:contracts:hazardous_approval_one",
    hazardousApprovalTwo: "edr_freight_app:contracts:hazardous_approval_two",
    generateContract: "edr_freight_app:contracts:generate_contract",
    signStaff: {
      bulk: "edr_freight_app:contracts:sign_staff:bulk",
      container: "edr_freight_app:contracts:sign_staff:container",
    },
    clearanceReview: "edr_freight_app:contracts:clearance_review",
    finalizeClearance: "edr_freight_app:contracts:finalize_clearance",
    createBooking: "edr_freight_app:contracts:create_booking",
    opsClearanceReview: "edr_freight_app:contracts:ops_clearance_review",
    clearanceDutyAdvise: "edr_freight_app:contracts:clearance_duty_advise",
    clearanceEtActions: "edr_freight_app:contracts:clearance_et_actions",
    clearanceDjActions: "edr_freight_app:contracts:clearance_dj_actions",
  },
  trainScheduling: {
    view: "edr_freight_app:train_scheduling:view",
    create: "edr_freight_app:train_scheduling:create",
    update: "edr_freight_app:train_scheduling:update",
    cancel: "edr_freight_app:train_scheduling:cancel",
    reschedule: "edr_freight_app:train_scheduling:reschedule",
    rulesManage: "edr_freight_app:train_scheduling:rules_manage",
  },
  fleet: {
    view: "edr_freight_app:fleet:view",
    manage: "edr_freight_app:fleet:manage",
  },
  admin: "edr_freight_app:admin",
  allocation: {
    manage: "edr_freight_app:allocation:manage",
  },
  customers: {
    view: "edr_freight_app:customers:view",
    create: "edr_freight_app:customers:create",
    update: "edr_freight_app:customers:update",
    deactivate: "edr_freight_app:customers:deactivate",
    verify: "edr_freight_app:customers:verify",
    resetPassword: "edr_freight_app:customers:reset-password",
  },
  payments: {
    view: "edr_freight_app:payments:view",
    verify: "edr_freight_app:payments:verify",
    refund: "edr_freight_app:payments:refund",
  },
  invoices: {
    view: "edr_freight_app:invoices:view",
    create: "edr_freight_app:invoices:create",
    cancel: "edr_freight_app:invoices:cancel",
    export: "edr_freight_app:invoices:export",
  },
  firstMile: {
    view: "edr_freight_app:first_mile:view",
    accept: "edr_freight_app:first_mile:accept",
    create: "edr_freight_app:first_mile:create",
    update: "edr_freight_app:first_mile:update",
    delete: "edr_freight_app:first_mile:delete",
    assignVehicles: "edr_freight_app:first_mile:assign_vehicles",
    setDistances: "edr_freight_app:first_mile:set_distances",
    generateInvoice: "edr_freight_app:first_mile:generate_invoice",
  },
  lastMile: {
    view: "edr_freight_app:last_mile:view",
    accept: "edr_freight_app:last_mile:accept",
    create: "edr_freight_app:last_mile:create",
    update: "edr_freight_app:last_mile:update",
    delete: "edr_freight_app:last_mile:delete",
    assignVehicles: "edr_freight_app:last_mile:assign_vehicles",
    setDistances: "edr_freight_app:last_mile:set_distances",
    generateInvoice: "edr_freight_app:last_mile:generate_invoice",
  },
  locomotives: {
    view: "edr_freight_app:locomotives:view",
    create: "edr_freight_app:locomotives:create",
    update: "edr_freight_app:locomotives:update",
    delete: "edr_freight_app:locomotives:delete",
  },
  wagons: {
    view: "edr_freight_app:wagons:view",
    create: "edr_freight_app:wagons:create",
    update: "edr_freight_app:wagons:update",
    delete: "edr_freight_app:wagons:delete",
    transferRequest: "edr_freight_app:wagons:transfer_request",
    transferFulfill: "edr_freight_app:wagons:transfer_fulfill",
    transferHistoryAll: "edr_freight_app:wagons:transfer_history_all",
    /** Open the transfer desk. `wagons:view` is accepted as a fallback. */
    transferView: "edr_freight_app:wagons:transfer_view",
    transferCancel: "edr_freight_app:wagons:transfer_cancel",
    transferCloseShort: "edr_freight_app:wagons:transfer_close_short",
  },
  trains: {
    view: "edr_freight_app:trains:view",
    create: "edr_freight_app:trains:create",
    update: "edr_freight_app:trains:update",
    delete: "edr_freight_app:trains:delete",
    assignWagons: "edr_freight_app:trains:assign_wagons",
  },
  routes: {
    view: "edr_freight_app:routes:view",
    create: "edr_freight_app:routes:create",
    update: "edr_freight_app:routes:update",
    delete: "edr_freight_app:routes:delete",
  },
  containers: {
    view: "edr_freight_app:containers:view",
    create: "edr_freight_app:containers:create",
    update: "edr_freight_app:containers:update",
    delete: "edr_freight_app:containers:delete",
  },
  cargoes: {
    view: "edr_freight_app:cargoes:view",
    create: "edr_freight_app:cargoes:create",
    update: "edr_freight_app:cargoes:update",
    delete: "edr_freight_app:cargoes:delete",
  },
  vehicles: {
    view: "edr_freight_app:vehicles:view",
    create: "edr_freight_app:vehicles:create",
    update: "edr_freight_app:vehicles:update",
    delete: "edr_freight_app:vehicles:delete",
  },
  drivers: {
    view: "edr_freight_app:drivers:view",
    create: "edr_freight_app:drivers:create",
    update: "edr_freight_app:drivers:update",
    delete: "edr_freight_app:drivers:delete",
  },
  tracking: {
    view: "edr_freight_app:tracking:view",
    manage: "edr_freight_app:tracking:manage",
  },
  fuel: {
    view: "edr_freight_app:fuel:view",
    create: "edr_freight_app:fuel:create",
    update: "edr_freight_app:fuel:update",
    delete: "edr_freight_app:fuel:delete",
    approve: "edr_freight_app:fuel:approve",
  },
  maintenance: {
    view: "edr_freight_app:maintenance:view",
    create: "edr_freight_app:maintenance:create",
    update: "edr_freight_app:maintenance:update",
    delete: "edr_freight_app:maintenance:delete",
    complete: "edr_freight_app:maintenance:complete",
  },
  fleetReports: {
    view: "edr_freight_app:fleet_reports:view",
    export: "edr_freight_app:fleet_reports:export",
  },
  fleetDashboard: {
    view: "edr_freight_app:fleet_dashboard:view",
  },
  warehouseDashboard: {
    view: "edr_freight_app:warehouse_dashboard:view",
  },
  warehouses: {
    view: "edr_freight_app:warehouses:view",
    create: "edr_freight_app:warehouses:create",
    update: "edr_freight_app:warehouses:update",
    delete: "edr_freight_app:warehouses:delete",
  },
  warehouseYards: {
    view: "edr_freight_app:warehouse_yards:view",
    create: "edr_freight_app:warehouse_yards:create",
    update: "edr_freight_app:warehouse_yards:update",
    delete: "edr_freight_app:warehouse_yards:delete",
  },
  warehouseZones: {
    view: "edr_freight_app:warehouse_zones:view",
    create: "edr_freight_app:warehouse_zones:create",
    update: "edr_freight_app:warehouse_zones:update",
  },
  warehouseAllocationRules: {
    view: "edr_freight_app:warehouse_allocation_rules:view",
    create: "edr_freight_app:warehouse_allocation_rules:create",
    update: "edr_freight_app:warehouse_allocation_rules:update",
    delete: "edr_freight_app:warehouse_allocation_rules:delete",
  },
  warehouseFeeRules: {
    view: "edr_freight_app:warehouse_fee_rules:view",
    create: "edr_freight_app:warehouse_fee_rules:create",
    update: "edr_freight_app:warehouse_fee_rules:update",
    delete: "edr_freight_app:warehouse_fee_rules:delete",
  },
  warehouseInspectionReports: {
    view: "edr_freight_app:warehouse_inspection_reports:view",
    create: "edr_freight_app:warehouse_inspection_reports:create",
    update: "edr_freight_app:warehouse_inspection_reports:update",
  },
  warehouseInventory: {
    view: "edr_freight_app:warehouse_inventory:view",
    receive: "edr_freight_app:warehouse_inventory:receive",
    move: "edr_freight_app:warehouse_inventory:move",
    load: "edr_freight_app:warehouse_inventory:load",
    unload: "edr_freight_app:warehouse_inventory:unload",
    dispatch: "edr_freight_app:warehouse_inventory:dispatch",
    gatePass: "edr_freight_app:warehouse_inventory:gate_pass",
    release: "edr_freight_app:warehouse_inventory:release",
    deliver: "edr_freight_app:warehouse_inventory:deliver",
    inspect: "edr_freight_app:warehouse_inventory:inspect",
  },
  interchangeDocuments: {
    view: "edr_freight_app:interchange_documents:view",
    generate: "edr_freight_app:interchange_documents:generate",
    acknowledge: "edr_freight_app:interchange_documents:acknowledge",
    dispute: "edr_freight_app:interchange_documents:dispute",
    cancel: "edr_freight_app:interchange_documents:cancel",
  },
  warehouseFeeInvoices: {
    view: "edr_freight_app:warehouse_fee_invoices:view",
    generate: "edr_freight_app:warehouse_fee_invoices:generate",
    cancel: "edr_freight_app:warehouse_fee_invoices:cancel",
    pay: "edr_freight_app:warehouse_fee_invoices:pay",
  },
  settings: {
    fileUpload: {
      view: "edr_freight_app:settings:file_upload:view",
      manage: "edr_freight_app:settings:file_upload:manage",
    },
    dropdown: {
      view: "edr_freight_app:settings:dropdown:view",
      manage: "edr_freight_app:settings:dropdown:manage",
    },
  },
  staff: {
    roles: {
      view: "edr_freight_app:staff:roles:view",
      create: "edr_freight_app:staff:roles:create",
      update: "edr_freight_app:staff:roles:update",
      delete: "edr_freight_app:staff:roles:delete",
    },
    permissions: {
      view: "edr_freight_app:staff:permissions:view",
      assign: "edr_freight_app:staff:permissions:assign",
    },
    employeeRegistration: {
      view: "edr_freight_app:employee_registration:view",
      create: "edr_freight_app:employee_registration:create",
      update: "edr_freight_app:employee_registration:update",
      activate: "edr_freight_app:employee_registration:activate",
      deactivate: "edr_freight_app:employee_registration:deactivate",
    },
    roleAssignment: {
      view: "edr_freight_app:role_assignment:view",
      assign: "edr_freight_app:role_assignment:assign",
      replace: "edr_freight_app:role_assignment:replace",
    },
    hierarchyUnits: {
      view: "edr_freight_app:hierarchy_units:view",
      create: "edr_freight_app:hierarchy_units:create",
      update: "edr_freight_app:hierarchy_units:update",
      delete: "edr_freight_app:hierarchy_units:delete",
    },
    hierarchyPositions: {
      view: "edr_freight_app:hierarchy_positions:view",
      create: "edr_freight_app:hierarchy_positions:create",
      update: "edr_freight_app:hierarchy_positions:update",
      delete: "edr_freight_app:hierarchy_positions:delete",
      changeParent: "edr_freight_app:hierarchy_positions:change_parent",
    },
    hierarchyEmployeeAssignment: {
      view: "edr_freight_app:hierarchy_employee_assignment:view",
      invite: "edr_freight_app:hierarchy_employee_assignment:invite",
      assign: "edr_freight_app:hierarchy_employee_assignment:assign",
    },
    positionTypes: {
      view: "edr_freight_app:position_types:view",
      create: "edr_freight_app:position_types:create",
      update: "edr_freight_app:position_types:update",
      delete: "edr_freight_app:position_types:delete",
    },
  },
} as const;

const slugToResourceKey = (slug: RuleEngineResourceSlug): string =>
  slug.replace(/-/g, "_");

export function getPermissionKeys(user: AuthUser | null | undefined): string[] {
  if (!user) return [];
  if (user.permissionKeys?.length) return user.permissionKeys;

  const keys = new Set<string>();
  for (const p of user.permissions ?? []) {
    if (p.key) keys.add(p.key);
  }
  for (const emp of user.employee ?? []) {
    for (const pos of emp.positions ?? []) {
      for (const p of pos.permissions ?? []) {
        if (p.key) keys.add(p.key);
      }
    }
  }
  return [...keys];
}

/**
 * Position keys held by the user (e.g. "ethiopian_gl", "djibouti_gl").
 * Tolerates IAM payload shape variants: the key flat on the employee position,
 * nested under `position.key`, or the GL modeled as a role instead.
 */
export function getPositionKeys(user: AuthUser | null | undefined): string[] {
  if (!user) return [];
  const keys = new Set<string>();
  for (const emp of user.employee ?? []) {
    for (const pos of emp.positions ?? []) {
      if (pos.key) keys.add(pos.key);
      if (pos.position?.key) keys.add(pos.position.key);
    }
  }
  for (const role of user.roles ?? []) {
    if (role.key) keys.add(role.key);
  }
  return [...keys];
}

export function hasPosition(
  user: AuthUser | null | undefined,
  positionKey: string,
): boolean {
  return getPositionKeys(user).includes(positionKey);
}

export const POSITION_KEYS = {
  ethiopianGl: "ethiopian_gl",
  djiboutiGl: "djibouti_gl",
} as const;

/** Position-type keys held by the user (e.g. "djibouti-gl-officer"). */
export function getPositionTypeKeys(
  user: AuthUser | null | undefined,
): string[] {
  if (!user) return [];
  const keys = new Set<string>();
  for (const emp of user.employee ?? []) {
    for (const pos of emp.positions ?? []) {
      if (pos.positionType?.key) keys.add(pos.positionType.key);
    }
  }
  return [...keys];
}

// GL staff are identified by the root position key (department heads) OR by
// their position-type key (sub-positions: director/chief/officer) — both
// forms get the clearance-only locked view.
const ET_GL_TYPE_PREFIX = "commercial-global-logistics-(et)";
const DJ_GL_TYPE_PREFIX = "djibouti-gl";

export function isEthiopianGl(user: AuthUser | null | undefined): boolean {
  return (
    hasPosition(user, POSITION_KEYS.ethiopianGl) ||
    getPositionTypeKeys(user).some((k) => k.startsWith(ET_GL_TYPE_PREFIX))
  );
}

export function isDjiboutiGl(user: AuthUser | null | undefined): boolean {
  return (
    hasPosition(user, POSITION_KEYS.djiboutiGl) ||
    getPositionTypeKeys(user).some((k) => k.startsWith(DJ_GL_TYPE_PREFIX))
  );
}

export function isSuperAdmin(user: AuthUser | null | undefined): boolean {
  if (user?.isSuperAdmin) return true;
  return Boolean(user?.roles?.some((r) => r.key === "super_admin"));
}

/** Org-level admins may act on any approval step in the chain. */
export function isOrganizationAdmin(
  user: AuthUser | null | undefined,
): boolean {
  return Boolean(user?.roles?.some((r) => r.key === "organization_admin"));
}

export function isFreightApprovalAdmin(
  user: AuthUser | null | undefined,
): boolean {
  return isSuperAdmin(user) || isOrganizationAdmin(user);
}

export function hasPermission(
  user: AuthUser | null | undefined,
  key: string,
): boolean {
  if (!user) return false;
  if (isSuperAdmin(user)) return true;
  return getPermissionKeys(user).includes(key);
}

// Legacy chain roles predate position types; map each to the position types
// that stand in for it. Mirror of the API's LEGACY_ROLE_POSITION_TYPES so the
// button visibility matches what the approve/reject endpoint will accept.
const LEGACY_ROLE_POSITION_TYPES: Record<string, string[]> = {
  LINE_STAFF: ["employee", "teamLeader", "officeHead", "recordOfficer"],
  DIRECTOR: ["director", "operation-director"],
  CEO: ["chief", "deputy"],
};

const CONTRACT_APPROVE_ROLE_PERMISSION: Record<string, string> = {
  LINE_STAFF: FREIGHT_PERMS.contracts.approveLineStaff,
  DIRECTOR: FREIGHT_PERMS.contracts.approveDirector,
  CEO: FREIGHT_PERMS.contracts.approveCeo,
};

/**
 * The two hazardous-goods steps prepended to a hazardous contract's chain.
 * They are not position types — they authorize purely on their own permission,
 * exactly as the API's HAZARDOUS_APPROVAL_ROLE_PERMISSION does.
 */
export const HAZARDOUS_APPROVAL_ROLE_PERMISSION: Record<string, string> = {
  HAZARDOUS_APPROVAL_ONE: FREIGHT_PERMS.contracts.hazardousApprovalOne,
  HAZARDOUS_APPROVAL_TWO: FREIGHT_PERMS.contracts.hazardousApprovalTwo,
};

/** Display label for an approval step's role (hazardous steps get real names). */
export const CONTRACT_APPROVAL_ROLE_LABELS: Record<string, string> = {
  HAZARDOUS_APPROVAL_ONE: "Hazardous review — first approver",
  HAZARDOUS_APPROVAL_TWO: "Hazardous review — second approver",
};

/**
 * Can this user action a contract approval step requiring `requiredRole`?
 *
 * `requiredRole` is an `iam.position_types.key` (the role vocabulary approval
 * chains are configured in), or a legacy LINE_STAFF/DIRECTOR/CEO string. Used
 * to show Approve/Reject only to the step's actual approver — a chief step
 * shows only to a chief, a marketing-officer step only to that officer.
 *
 * Deliberately STRICTER than the API's `assertCanApproveContractStep`, which
 * also lets through anyone holding any contract-approve permission (a fallback
 * for delegates whose token omits the position type). That blanket is what made
 * every approver see the button, so it is dropped here: the visibility rule is
 * admin OR the matching position type (direct / legacy alias) OR the role's own
 * legacy approve permission. The server still guards the mutation.
 */
export function canApproveContractStep(
  user: AuthUser | null | undefined,
  requiredRole: string | null | undefined,
): boolean {
  if (!user || !requiredRole) return false;
  if (isFreightApprovalAdmin(user)) return true;

  // Hazardous steps are permission-only — no position type stands in for them.
  const hazardousPermission = HAZARDOUS_APPROVAL_ROLE_PERMISSION[requiredRole];
  if (hazardousPermission) return hasPermission(user, hazardousPermission);

  const positionTypes = getPositionTypeKeys(user);
  if (positionTypes.includes(requiredRole)) return true;

  const aliases = LEGACY_ROLE_POSITION_TYPES[requiredRole] ?? [];
  if (aliases.some((alias) => positionTypes.includes(alias))) return true;

  const legacyPermission = CONTRACT_APPROVE_ROLE_PERMISSION[requiredRole];
  return Boolean(legacyPermission && hasPermission(user, legacyPermission));
}

export function canAccessBookings(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.bookings.view);
}

/**
 * Sees the header countdown warning that document review is about to end with
 * requests still undecided. Its own permission — granted per position type, so
 * only the desks that act on those requests get alarmed.
 */
export function canSeeDocReviewAlert(
  user: AuthUser | null | undefined,
): boolean {
  return hasPermission(user, FREIGHT_PERMS.bookings.docReviewAlert);
}

export function canAccessContracts(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.contracts.view);
}

/** Can review the GL Ethiopia pre-booking contract clearance queue (Path B). */
export function canReviewContractClearance(
  user: AuthUser | null | undefined,
): boolean {
  return hasPermission(user, FREIGHT_PERMS.contracts.clearanceReview);
}

/** GL Ethiopia: can create a booking under a cleared contract (Path B). */
export function canCreateContractBooking(
  user: AuthUser | null | undefined,
): boolean {
  return hasPermission(user, FREIGHT_PERMS.contracts.createBooking);
}

/** Operations: can review the Path A self-clearance queue (non-customs). */
export function canReviewSelfClearance(
  user: AuthUser | null | undefined,
): boolean {
  return hasPermission(user, FREIGHT_PERMS.contracts.opsClearanceReview);
}

/** Can see/manage the customs document-clearance queue (Global Logistics). */
export function canViewClearance(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.bookings.reviewDocuments);
}

export function canViewScheduling(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.trainScheduling.view);
}

/** Any train-scheduling write action (create / update / cancel / reschedule). */
export function canManageScheduling(user: AuthUser | null | undefined): boolean {
  return (
    hasPermission(user, FREIGHT_PERMS.trainScheduling.create) ||
    hasPermission(user, FREIGHT_PERMS.trainScheduling.update) ||
    hasPermission(user, FREIGHT_PERMS.trainScheduling.cancel) ||
    hasPermission(user, FREIGHT_PERMS.trainScheduling.reschedule)
  );
}

export function canCreateSchedule(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.trainScheduling.create);
}

/** Dispatching a train and opening/closing its booking window are both updates. */
export function canUpdateSchedule(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.trainScheduling.update);
}

export function canViewFleet(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.fleet.view);
}

export type FleetCrudResource =
  | "locomotives"
  | "wagons"
  | "trains"
  | "routes"
  | "containers"
  | "cargoes"
  | "vehicles"
  | "drivers";

/**
 * Per-resource fleet CRUD check. The legacy coarse fleet:manage key still
 * grants every action (mirrors the API's one-of guard fallback).
 */
export function canFleetAction(
  user: AuthUser | null | undefined,
  resource: FleetCrudResource,
  action: "create" | "update" | "delete",
): boolean {
  return (
    hasPermission(user, FREIGHT_PERMS[resource][action]) ||
    hasPermission(user, FREIGHT_PERMS.fleet.manage)
  );
}

export function isFreightAdmin(user: AuthUser | null | undefined): boolean {
  return hasPermission(user, FREIGHT_PERMS.admin);
}

export type RuleEngineAction = "view" | "create" | "update" | "delete";

export function ruleEngineActionKey(
  slug: RuleEngineResourceSlug,
  action: RuleEngineAction,
): string {
  return `edr_freight_app:rule_engine:${slugToResourceKey(slug)}:${action}`;
}

export function ruleEngineViewKey(slug: RuleEngineResourceSlug): string {
  return ruleEngineActionKey(slug, "view");
}

/**
 * Deciding a filed change — a step above `manage`, which only lets a staff
 * member propose one. Only resources with an approval workflow have it.
 */
export function ruleEngineApproveKey(slug: "rates"): string {
  return `edr_freight_app:rule_engine:${slugToResourceKey(slug)}:approve`;
}

export function canApproveRuleEngineChange(
  user: AuthUser | null | undefined,
  slug: "rates",
): boolean {
  return hasPermission(user, ruleEngineApproveKey(slug));
}

export function canAccessRuleEngineResource(
  user: AuthUser | null | undefined,
  slug: RuleEngineResourceSlug,
  mode: RuleEngineAction,
): boolean {
  return hasPermission(user, ruleEngineActionKey(slug, mode));
}

/** Holds any write action on the resource — for surfaces gated on "can edit at all". */
export function canWriteRuleEngineResource(
  user: AuthUser | null | undefined,
  slug: RuleEngineResourceSlug,
): boolean {
  return (["create", "update", "delete"] as const).some((a) =>
    canAccessRuleEngineResource(user, slug, a),
  );
}

export function canAccessAnyRuleEngineView(
  user: AuthUser | null | undefined,
  slugs: RuleEngineResourceSlug[],
): boolean {
  return slugs.some((slug) => canAccessRuleEngineResource(user, slug, "view"));
}
