import { beforeEach, describe, expect, it, vi } from 'vitest';
import { AuthorizationService } from './AuthorizationService';

describe('AuthorizationService', () => {
  let service: AuthorizationService;

  beforeEach(() => {
    // Clear environment variables
    delete process.env.GRIDPILOT_AUTHZ_CACHE_MS;
    delete process.env.GRIDPILOT_USER_ROLES_JSON;
    
    service = new AuthorizationService();
  });

  describe('getRolesForUser', () => {
    it('should return empty array when no roles are configured', () => {
      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual([]);
    });

    it('should return roles from environment variable', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin', 'owner'],
        'user-456': ['user'],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin', 'owner']);
    });

    it('should return empty array for user not in roles config', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });

      const roles = service.getRolesForUser('user-456');
      expect(roles).toEqual([]);
    });

    it('should cache roles and return cached values', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });
      process.env.GRIDPILOT_AUTHZ_CACHE_MS = '10000';

      // First call
      const roles1 = service.getRolesForUser('user-123');
      expect(roles1).toEqual(['admin']);

      // Second call should return cached value
      const roles2 = service.getRolesForUser('user-123');
      expect(roles2).toEqual(['admin']);
    });

    it('should handle invalid JSON gracefully', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = 'invalid json';

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual([]);
    });

    it('should handle non-object JSON gracefully', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify('not an object');

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual([]);
    });

    it('should filter out non-string roles', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin', 123, null, 'owner', undefined, 'user'],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin', 'owner', 'user']);
    });

    it('should trim whitespace from roles', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['  admin  ', '  owner  '],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin', 'owner']);
    });

    it('should filter out empty strings after trimming', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin', '   ', 'owner'],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin', 'owner']);
    });

    it('should use default cache time when not configured', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin']);
    });

    it('should use configured cache time', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });
      process.env.GRIDPILOT_AUTHZ_CACHE_MS = '5000';

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin']);
    });

    it('should handle invalid cache time gracefully', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });
      process.env.GRIDPILOT_AUTHZ_CACHE_MS = 'invalid';

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin']);
    });

    it('should handle negative cache time gracefully', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': ['admin'],
      });
      process.env.GRIDPILOT_AUTHZ_CACHE_MS = '-1000';

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual(['admin']);
    });

    it('should handle empty roles array', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123': [],
      });

      const roles = service.getRolesForUser('user-123');
      expect(roles).toEqual([]);
    });

    it('should handle user ID with special characters', () => {
      process.env.GRIDPILOT_USER_ROLES_JSON = JSON.stringify({
        'user-123@example.com': ['admin'],
      });

      const roles = service.getRolesForUser('user-123@example.com');
      expect(roles).toEqual(['admin']);
    });
  });
});
