/// 권한 검사에 사용하는 리소스 경로 상수를 정의하고 정규화 유틸을 제공한다.
///
/// - UI 라우트 경로(`/inventory/inbound` 등)를 서버 표준 경로(`/stock-transactions`)
///   로 변환해 [PermissionManager]와 환경 설정이 동일한 키를 사용하도록 맞춘다.
class PermissionResources {
  const PermissionResources._();

  static const String dashboard = '/dashboard';
  static const String stockTransactions = '/stock-transactions';
  static const String approvals = '/approvals';
  static const String approvalSteps = '/approval-steps';
  static const String approvalHistories = '/approval-histories';
  static const String approvalTemplates = '/approval/templates';
  static const String inventorySummary = '/inventory/summary';
  static const String inventoryScope = 'scope:inventory.view';
  static const String groupMenuPermissions = '/group-menu-permissions';
  static const String vendors = '/vendors';
  static const String products = '/products';
  static const String warehouses = '/warehouses';
  static const String customers = '/customers';
  static const String users = '/users';
  static const String groups = '/groups';
  static const String menus = '/menus';
  static const String postalSearch = '/zipcodes';
  static const String reports = '/reports';
  static const String reportsTransactions = '/reports/transactions';
  static const String reportsApprovals = '/reports/approvals';

  /// 라우트/엔드포인트 별칭을 표준 경로로 매핑한 테이블.
  static const Map<String, String> _aliases = {
    '/dashboard': dashboard,
    '/inventory': stockTransactions,
    '/inventory/inbound': stockTransactions,
    '/inventory/outbound': stockTransactions,
    '/inventory/rental': stockTransactions,
    '/approvals/requests': approvals,
    '/approvals': approvals,
    '/approvals/steps': approvalSteps,
    '/approval-steps': approvalSteps,
    '/approvals/history': approvalHistories,
    '/approvals/histories': approvalHistories,
    '/approval-histories': approvalHistories,
    '/approvals/templates': approvalTemplates,
    '/approval/templates': approvalTemplates,
    '/approval-templates': approvalTemplates,
    '/inventory/summary': inventorySummary,
    '/masters/group-permissions': groupMenuPermissions,
    '/group-menu-permissions': groupMenuPermissions,
    '/masters/vendors': vendors,
    '/vendors': vendors,
    '/masters/products': products,
    '/products': products,
    '/masters/warehouses': warehouses,
    '/warehouses': warehouses,
    '/masters/customers': customers,
    '/customers': customers,
    '/masters/users': users,
    '/users': users,
    '/masters/groups': groups,
    '/groups': groups,
    '/masters/menus': menus,
    '/menus': menus,
    '/utilities/postal-search': postalSearch,
    '/zipcodes': postalSearch,
    '/reports': reports,
    '/reports/transactions': reportsTransactions,
    '/reports/transactions/export': reportsTransactions,
    '/reports/approvals': reportsApprovals,
    '/reports/approvals/export': reportsApprovals,
  };

  /// 주어진 [resource] 문자열을 서버 표준 경로로 정규화한다.
  ///
  /// - 앞뒤 공백 및 대소문자를 정리한다.
  /// - 맵에 등록된 라우트/별칭을 모두 표준 경로로 통일한다.
  static String normalize(String resource) {
    final sanitized = _sanitize(resource);
    if (sanitized.isEmpty) {
      return sanitized;
    }
    return _aliases[sanitized] ?? sanitized;
  }

  static String _sanitize(String resource) {
    final trimmed = resource.trim();
    if (trimmed.isEmpty) {
      return '';
    }
    final lowered = trimmed.toLowerCase();
    if (lowered.startsWith('scope:')) {
      return lowered;
    }
    var normalized = lowered;

    // 절대 URL이 들어오면 path 부분만 추출한다.
    final uri = Uri.tryParse(normalized);
    if (uri != null && uri.hasScheme) {
      normalized = uri.path;
    }

    // 쿼리스트링이나 프래그먼트를 제거해 순수 경로만 남긴다.
    final queryIndex = normalized.indexOf('?');
    if (queryIndex != -1) {
      normalized = normalized.substring(0, queryIndex);
    }
    final hashIndex = normalized.indexOf('#');
    if (hashIndex != -1) {
      normalized = normalized.substring(0, hashIndex);
    }

    if (!normalized.startsWith('/')) {
      normalized = '/$normalized';
    }

    while (normalized.contains('//')) {
      normalized = normalized.replaceAll('//', '/');
    }

    if (normalized.length > 1 && normalized.endsWith('/')) {
      normalized = normalized.substring(0, normalized.length - 1);
    }
    return normalized;
  }
}
