// tests/reflection/policy.spec.ts
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import {
  getPolicyState,
  getPolicyValue,
  applyPolicyAdjustments,
  rollbackPolicy,
  _resetPolicyManager,
} from '@/lib/reflection/policy';
import type { PolicyAdjustment } from '@/lib/reflection/types';
import * as flags from '@/lib/reflection/flags';

/**
 * Reflection Policy Engine Tests
 *
 * Validates:
 *  - Default initialization
 *  - Versioned updates and rollback
 *  - Dry-run and verbose flag effects
 *  - Reset integrity
 */

describe('Reflection Policy Engine', () => {
  beforeEach(() => {
    vi.useRealTimers();
    vi.useFakeTimers();
    vi.setSystemTime(0);
    _resetPolicyManager?.();
  });

  afterEach(() => {
    vi.runOnlyPendingTimers();
    vi.useRealTimers();
    vi.restoreAllMocks();
  });

  // ---------------------------------------------------------
  // 1. Default State
  // ---------------------------------------------------------
  it('should start with default policies', () => {
    const state = getPolicyState();
    expect(state.version).toBe(1);
    expect(Object.keys(state.policies)).toContain('THROTTLE_WINDOWS');
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(100);
  });

  // ---------------------------------------------------------
  // 2. Apply Adjustments + Version Increment
  // ---------------------------------------------------------
  it('should apply policy adjustments and increment version', () => {
    const adjustments: PolicyAdjustment[] = [
      { policyName: 'THROTTLE_WINDOWS', newValue: 500 },
      { policyName: 'DEFER_ANIMATIONS', newValue: true },
    ];

    const before = getPolicyState();
    const after = applyPolicyAdjustments(adjustments);

    expect(after.version).toBeGreaterThan(before.version);
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(500);
    expect(getPolicyValue('DEFER_ANIMATIONS')).toBe(true);
  });

  // ---------------------------------------------------------
  // 3. Skip Increment if No Actual Change
  // ---------------------------------------------------------
  it('should not increment version if no actual change occurs', () => {
    const before = getPolicyState();
    const adjustments: PolicyAdjustment[] = [{ policyName: 'THROTTLE_WINDOWS', newValue: 100 }];

    const after = applyPolicyAdjustments(adjustments);
    expect(after.version).toBe(before.version);
  });

  // ---------------------------------------------------------
  // 4. Dry-Run Mode
  // ---------------------------------------------------------
  it('should not mutate state when dry-run flag is active', () => {
    const drySpy = vi.spyOn(flags, 'isDryRun').mockReturnValue(true);
    const verboseSpy = vi.spyOn(flags, 'isVerbose').mockReturnValue(false);

    const beforeValue = getPolicyValue('THROTTLE_WINDOWS');
    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 777 }]);
    const afterValue = getPolicyValue('THROTTLE_WINDOWS');

    expect(afterValue).toBe(beforeValue);

    drySpy.mockRestore();
    verboseSpy.mockRestore();
  });

  // ---------------------------------------------------------
  // 5. Verbose Logging
  // ---------------------------------------------------------
  it('should log policy updates when verbose mode is active', () => {
    const verboseSpy = vi.spyOn(flags, 'isVerbose').mockReturnValue(true);
    const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});

    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 333 }]);
    expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('THROTTLE_WINDOWS'));

    verboseSpy.mockRestore();
    logSpy.mockRestore();
  });

  // ---------------------------------------------------------
  // 6. Rollback
  // ---------------------------------------------------------
  it('should rollback to a previous version correctly', () => {
    const adjustments: PolicyAdjustment[] = [{ policyName: 'THROTTLE_WINDOWS', newValue: 400 }];
    const updated = applyPolicyAdjustments(adjustments);
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(400);

    const rolled = rollbackPolicy(updated.version - 1);
    expect(rolled).not.toBeNull();
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(100);
  });

  // ---------------------------------------------------------
  // 7. Invalid Rollback
  // ---------------------------------------------------------
  it('should handle invalid rollback attempts gracefully', () => {
    const result = rollbackPolicy(999);
    expect(result).toBeNull();
  });

  // ---------------------------------------------------------
  // 8. Chained Version History
  // ---------------------------------------------------------
  it('should correctly restore from a chain of versioned changes', () => {
    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 200 }]);
    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 300 }]);
    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 400 }]);

    const state = getPolicyState();
    expect(state.version).toBeGreaterThan(1);

    rollbackPolicy(1);
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(100);
  });

  // ---------------------------------------------------------
  // 9. Reset Integrity
  // ---------------------------------------------------------
  it('should reset to initial state when reset is called', () => {
    applyPolicyAdjustments([{ policyName: 'THROTTLE_WINDOWS', newValue: 200 }]);
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(200);

    _resetPolicyManager();
    expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(100);
  });
});
