import { describe, it, expect } from 'vitest';
import { resolveAutonomy, type AutonomyLevel } from './autonomy.js';
import type { HookAction } from './types.js';

describe('autonomy', () => {
  describe('resolveAutonomy', () => {
    describe('conservative mode', () => {
      const level: AutonomyLevel = 'conservative';

      it('overrides silent to confirm for dangerous tools', () => {
        const decision = resolveAutonomy('file.write', 'silent', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(true);
        expect(decision.reason).toContain('conservative mode');
        expect(decision.level).toBe('conservative');
      });

      it('preserves confirm for dangerous tools', () => {
        const decision = resolveAutonomy('shell.exec', 'confirm', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(false);
        expect(decision.reason).toContain('already requires confirmation');
      });

      it('allows safe read tools with base action', () => {
        const decision = resolveAutonomy('file.read', 'silent', level);
        expect(decision.action).toBe('silent');
        expect(decision.overridden).toBe(false);
        expect(decision.reason).toContain('safe');
      });

      it('handles all dangerous tools', () => {
        const dangerous = ['file.write', 'file.edit', 'file.patch', 'shell.exec', 'process.start', 'process.kill'];
        for (const tool of dangerous) {
          const decision = resolveAutonomy(tool, 'silent', level);
          expect(decision.action).toBe('confirm');
          expect(decision.overridden).toBe(true);
        }
      });
    });

    describe('standard mode', () => {
      const level: AutonomyLevel = 'standard';

      it('overrides silent to confirm for dangerous tools without explicit hook', () => {
        const decision = resolveAutonomy('file.write', 'silent', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(true);
        expect(decision.reason).toContain('standard mode');
        expect(decision.reason).toContain('dangerous tool without explicit hook');
      });

      it('preserves confirm for dangerous tools', () => {
        const decision = resolveAutonomy('shell.exec', 'confirm', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(false);
      });

      it('preserves log for dangerous tools', () => {
        const decision = resolveAutonomy('file.edit', 'log', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(true);
      });

      it('allows safe tools with base action', () => {
        const decision = resolveAutonomy('file.read', 'silent', level);
        expect(decision.action).toBe('silent');
        expect(decision.overridden).toBe(false);
      });

      it('allows non-dangerous tools with any base action', () => {
        const decision = resolveAutonomy('custom.tool', 'silent', level);
        expect(decision.action).toBe('silent');
        expect(decision.overridden).toBe(false);
      });
    });

    describe('autonomous mode', () => {
      const level: AutonomyLevel = 'autonomous';

      it('defers to base action by default', () => {
        const decision = resolveAutonomy('file.write', 'silent', level);
        expect(decision.action).toBe('silent');
        expect(decision.overridden).toBe(false);
        expect(decision.reason).toContain('Base action');
      });

      it('preserves log action', () => {
        const decision = resolveAutonomy('shell.exec', 'log', level);
        expect(decision.action).toBe('log');
        expect(decision.overridden).toBe(false);
      });

      it('preserves explicit confirm hooks', () => {
        const decision = resolveAutonomy('dangerous.operation', 'confirm', level);
        expect(decision.action).toBe('confirm');
        expect(decision.overridden).toBe(false);
        expect(decision.reason).toContain("Base action 'confirm'");
      });

      it('does not force confirmation for dangerous tools', () => {
        const dangerous = ['file.write', 'file.edit', 'file.patch', 'shell.exec', 'process.start', 'process.kill'];
        for (const tool of dangerous) {
          const decision = resolveAutonomy(tool, 'silent', level);
          expect(decision.action).toBe('silent');
        }
      });
    });

    describe('action matrix coverage', () => {
      it('handles all combinations of levels and base actions', () => {
        const levels: AutonomyLevel[] = ['conservative', 'standard', 'autonomous'];
        const actions: HookAction[] = ['silent', 'log', 'confirm'];
        const tools = ['file.write', 'file.read', 'custom.tool'];

        for (const level of levels) {
          for (const action of actions) {
            for (const tool of tools) {
              const decision = resolveAutonomy(tool, action, level);
              expect(decision.action).toBeDefined();
              expect(decision.level).toBe(level);
              expect(decision.reason).toBeTruthy();
              expect(typeof decision.overridden).toBe('boolean');
            }
          }
        }
      });
    });

    describe('metadata', () => {
      it('always includes reason and level', () => {
        const decision = resolveAutonomy('file.write', 'silent', 'conservative');
        expect(decision.reason).toBeTruthy();
        expect(decision.reason.length).toBeGreaterThan(0);
        expect(decision.level).toBe('conservative');
      });

      it('marks overridden correctly', () => {
        // Conservative mode overrides
        expect(resolveAutonomy('file.write', 'silent', 'conservative').overridden).toBe(true);
        expect(resolveAutonomy('file.read', 'silent', 'conservative').overridden).toBe(false);

        // Autonomous mode does not override
        expect(resolveAutonomy('shell.exec', 'log', 'autonomous').overridden).toBe(false);
        expect(resolveAutonomy('shell.exec', 'silent', 'autonomous').overridden).toBe(false);
      });
    });
  });
});
