import { describe, expect, it, vi } from 'vitest';
import { PolicyController } from './PolicyController';
import { PolicySnapshot } from './PolicyService';

describe('PolicyController', () => {
  let controller: PolicyController;
  let mockService: { getSnapshot: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockService = {
      getSnapshot: vi.fn(),
    };

    controller = new PolicyController(mockService as never);
  });

  describe('getSnapshot', () => {
    it('should return policy snapshot from service', async () => {
      const mockSnapshot: PolicySnapshot = {
        policyVersion: 1,
        operationalMode: 'normal',
        maintenanceAllowlist: {
          view: ['health'],
          mutate: ['admin'],
        },
        capabilities: {
          'feature-a': 'enabled',
          'feature-b': 'disabled',
        },
        loadedFrom: 'defaults',
        loadedAtIso: new Date().toISOString(),
      };

      mockService.getSnapshot.mockResolvedValue(mockSnapshot);

      const result = await controller.getSnapshot();

      expect(mockService.getSnapshot).toHaveBeenCalledTimes(1);
      expect(result).toEqual(mockSnapshot);
    });

    it('should return snapshot with maintenance mode', async () => {
      const mockSnapshot: PolicySnapshot = {
        policyVersion: 2,
        operationalMode: 'maintenance',
        maintenanceAllowlist: {
          view: ['health', 'status'],
          mutate: ['admin'],
        },
        capabilities: {
          'dashboard': 'enabled',
          'payments': 'disabled',
        },
        loadedFrom: 'file',
        loadedAtIso: new Date().toISOString(),
      };

      mockService.getSnapshot.mockResolvedValue(mockSnapshot);

      const result = await controller.getSnapshot();

      expect(result).toEqual(mockSnapshot);
      expect(result.operationalMode).toBe('maintenance');
    });

    it('should return snapshot with test mode', async () => {
      const mockSnapshot: PolicySnapshot = {
        policyVersion: 1,
        operationalMode: 'test',
        maintenanceAllowlist: {
          view: [],
          mutate: [],
        },
        capabilities: {
          'all-features': 'enabled',
        },
        loadedFrom: 'env',
        loadedAtIso: new Date().toISOString(),
      };

      mockService.getSnapshot.mockResolvedValue(mockSnapshot);

      const result = await controller.getSnapshot();

      expect(result).toEqual(mockSnapshot);
      expect(result.operationalMode).toBe('test');
    });

    it('should return snapshot with empty capabilities', async () => {
      const mockSnapshot: PolicySnapshot = {
        policyVersion: 1,
        operationalMode: 'normal',
        maintenanceAllowlist: {
          view: [],
          mutate: [],
        },
        capabilities: {},
        loadedFrom: 'defaults',
        loadedAtIso: new Date().toISOString(),
      };

      mockService.getSnapshot.mockResolvedValue(mockSnapshot);

      const result = await controller.getSnapshot();

      expect(result).toEqual(mockSnapshot);
      expect(Object.keys(result.capabilities)).toHaveLength(0);
    });

    it('should return snapshot with coming_soon features', async () => {
      const mockSnapshot: PolicySnapshot = {
        policyVersion: 1,
        operationalMode: 'normal',
        maintenanceAllowlist: {
          view: [],
          mutate: [],
        },
        capabilities: {
          'new-feature': 'coming_soon',
          'beta-feature': 'hidden',
        },
        loadedFrom: 'file',
        loadedAtIso: new Date().toISOString(),
      };

      mockService.getSnapshot.mockResolvedValue(mockSnapshot);

      const result = await controller.getSnapshot();

      expect(result.capabilities['new-feature']).toBe('coming_soon');
      expect(result.capabilities['beta-feature']).toBe('hidden');
    });
  });
});