import { inject, InjectionToken } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';

/**
 * Token provider interface for role checking
 * The app can provide a custom implementation that returns user roles from the auth token
 */
export interface TokenProvider {
  /**
   * Get a claim value from the authentication token
   * @param key The claim key (e.g., 'role')
   * @returns The claim value or null if not found
   */
  getClaimByKey(key: string): unknown;
}

/**
 * Parse JWT token to extract claims
 */
export function parseJwt(token: string | null): Record<string, unknown> | null {
  if (!token) {
    return null;
  }

  try {
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const encoded = window.atob(base64);
    return JSON.parse(encoded);
  } catch {
    return null;
  }
}

/**
 * Injection token for TokenProvider with default OAuthService implementation
 *
 * By default, this uses OAuthService to extract claims from the access token.
 * You can override this by providing your own implementation:
 *
 * @example
 * ```typescript
 * providers: [
 *   {
 *     provide: TOKEN_PROVIDER,
 *     useValue: {
 *       getClaimByKey: (key) => customTokenService.getClaim(key)
 *     }
 *   }
 * ]
 * ```
 */
export const TOKEN_PROVIDER = new InjectionToken<TokenProvider>(
  'TOKEN_PROVIDER',
  {
    providedIn: 'root',
    factory: () => {
      const oAuthService = inject(OAuthService);
      return {
        getClaimByKey: (key: string) => {
          const claims = parseJwt(oAuthService.getAccessToken());
          return claims?.[key] ?? null;
        },
      };
    },
  },
);
