/**
 * Unit tests for src/services/ComplianceStatusStore.ts
 *
 * Uses jest.isolateModules to reset module-level state between test groups
 * since the store is a module-level Map singleton.
 */

describe('ComplianceStatusStore', () => {
  // Re-import the module fresh for each describe block to reset state
  let updateControlStatus: (id: string, status: string) => void;
  let getAllControlStatuses: () => unknown[];
  let getControlStatus: (id: string) => unknown;

  beforeEach(() => {
    jest.resetModules();
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const store = require('../../../src/services/ComplianceStatusStore');
    updateControlStatus = store.updateControlStatus;
    getAllControlStatuses = store.getAllControlStatuses;
    getControlStatus = store.getControlStatus;
  });

  describe('getAllControlStatuses()', () => {
    it('should return 5 controls on fresh module load', () => {
      const statuses = getAllControlStatuses();
      expect(statuses).toHaveLength(5);
    });

    it('should default all controls to unknown status', () => {
      const statuses = getAllControlStatuses() as Array<{ status: string }>;
      expect(statuses.every((s) => s.status === 'unknown')).toBe(true);
    });

    it('should return controls in canonical order', () => {
      const statuses = getAllControlStatuses() as Array<{ id: string }>;
      const ids = statuses.map((s) => s.id);
      expect(ids).toEqual(['CC6.1', 'CC6.7', 'CC7.2', 'CC9.2', 'CC7.1']);
    });

    it('should include name and lastChecked fields on each control', () => {
      const statuses = getAllControlStatuses() as Array<{ id: string; name: string; lastChecked: string }>;
      for (const s of statuses) {
        expect(typeof s.name).toBe('string');
        expect(s.name.length).toBeGreaterThan(0);
        expect(typeof s.lastChecked).toBe('string');
        expect(() => new Date(s.lastChecked)).not.toThrow();
      }
    });

    it('should map CC6.1 to Encryption at Rest', () => {
      const statuses = getAllControlStatuses() as Array<{ id: string; name: string }>;
      const cc61 = statuses.find((s) => s.id === 'CC6.1');
      expect(cc61?.name).toBe('Encryption at Rest');
    });
  });

  describe('updateControlStatus()', () => {
    it('should update a control to passing', () => {
      updateControlStatus('CC6.1', 'passing');
      const status = getControlStatus('CC6.1') as { status: string };
      expect(status.status).toBe('passing');
    });

    it('should update a control to failing', () => {
      updateControlStatus('CC7.2', 'failing');
      const status = getControlStatus('CC7.2') as { status: string };
      expect(status.status).toBe('failing');
    });

    it('should overwrite a previous status', () => {
      updateControlStatus('CC9.2', 'passing');
      updateControlStatus('CC9.2', 'failing');
      const status = getControlStatus('CC9.2') as { status: string };
      expect(status.status).toBe('failing');
    });

    it('should update lastChecked timestamp on each update', async () => {
      const before = Date.now();
      updateControlStatus('CC7.1', 'passing');
      const status = getControlStatus('CC7.1') as { lastChecked: string };
      const after = new Date(status.lastChecked).getTime();
      expect(after).toBeGreaterThanOrEqual(before);
    });

    it('should not affect other controls when one is updated', () => {
      updateControlStatus('CC6.1', 'passing');
      const all = getAllControlStatuses() as Array<{ id: string; status: string }>;
      const others = all.filter((s) => s.id !== 'CC6.1');
      expect(others.every((s) => s.status === 'unknown')).toBe(true);
    });
  });

  describe('getControlStatus()', () => {
    it('should return the correct control record', () => {
      updateControlStatus('CC6.7', 'passing');
      const status = getControlStatus('CC6.7') as { id: string; name: string; status: string };
      expect(status.id).toBe('CC6.7');
      expect(status.name).toBe('TLS Enforcement');
      expect(status.status).toBe('passing');
    });
  });
});
