import { coerceArray } from '@angular/cdk/coercion';
import { inject, Injectable } from '@angular/core';
import { logger } from '@isa/core/logging';
import { TOKEN_PROVIDER } from './token-provider';
import { Role } from './role';

/**
 * Service for role-based authorization checks
 *
 * @example
 * ```typescript
 * import { Role } from '@isa/core/auth';
 *
 * const roleService = inject(RoleService);
 * if (roleService.hasRole(Role.Store)) {
 *   // Show store features
 * }
 * ```
 */
@Injectable({
  providedIn: 'root',
})
export class RoleService {
  private readonly _log = logger({ service: 'RoleService' });
  private readonly _tokenProvider = inject(TOKEN_PROVIDER);

  /**
   * Check if the authenticated user has specific role(s)
   *
   * @param role Single role or array of roles to check
   * @returns true if user has all specified roles, false otherwise
   *
   * @example
   * ```typescript
   * import { Role } from '@isa/core/auth';
   *
   * // Check single role
   * hasRole(Role.Store) // true if user has Store role
   *
   * // Check multiple roles (AND logic)
   * hasRole([Role.Store, Role.CallCenter]) // true only if user has BOTH roles
   * ```
   */
  hasRole(role: Role | Role[]): boolean {
    const roles = coerceArray(role);

    try {
      const userRoles = this._tokenProvider.getClaimByKey('role');

      if (!userRoles) {
        this._log.debug('No roles found in token claims');
        return false;
      }

      // Coerce userRoles to array in case it's a single string
      const userRolesArray = coerceArray(userRoles);

      const hasAllRoles = roles.every((r) => userRolesArray.includes(r));

      this._log.debug(`Role check: ${roles.join(', ')} => ${hasAllRoles}`, () => ({
        requiredRoles: roles,
        userRoles: userRolesArray,
      }));

      return hasAllRoles;
    } catch (error) {
      this._log.error('Error checking roles', error as Error, () => ({ requiredRoles: roles }));
      return false;
    }
  }
}
