import { describe, it, expect } from 'vitest';
import {
  mergePermissions,
  matchRule,
  checkBashPermission,
  checkFilePathPermission,
  SYSTEM_DEFAULT_PERMISSION,
} from '../../../src/agent/permission-merger.js';
import type { AgentPermission, AgentBashPermission } from '../../../src/agent/types.js';

describe('matchRule - 命令规则匹配', () => {
  describe('通配符 * 匹配', () => {
    it('git diff* 匹配 git diff --staged', () => {
      expect(matchRule('git diff --staged', 'git diff*')).toBe(true);
    });

    it('git diff* 不匹配 git status', () => {
      expect(matchRule('git status', 'git diff*')).toBe(false);
    });

    it('rm -rf* 匹配危险命令', () => {
      expect(matchRule('rm -rf /', 'rm -rf*')).toBe(true);
      expect(matchRule('rm -rf /home/user', 'rm -rf*')).toBe(true);
    });

    it('rm -rf* 不匹配普通 rm', () => {
      expect(matchRule('rm file.txt', 'rm -rf*')).toBe(false);
    });
  });

  describe('精确匹配', () => {
    it('pwd 精确匹配', () => {
      expect(matchRule('pwd', 'pwd')).toBe(true);
    });

    it('pwd 不匹配带参数', () => {
      expect(matchRule('pwd /home', 'pwd')).toBe(false);
    });
  });

  describe('大小写不敏感', () => {
    it('忽略大小写', () => {
      expect(matchRule('GIT DIFF', 'git diff*')).toBe(true);
    });
  });
});

describe('checkBashPermission - Bash 权限检查', () => {
  it('禁用时返回 deny', () => {
    const permission: AgentBashPermission = { enabled: false };
    expect(checkBashPermission('ls', permission)).toBe('deny');
  });

  it('匹配 allow 规则', () => {
    const permission: AgentBashPermission = {
      enabled: true,
      rules: [{ pattern: 'ls *', action: 'allow' }],
      default: 'deny',
    };
    expect(checkBashPermission('ls -la', permission)).toBe('allow');
  });

  it('匹配 deny 规则', () => {
    const permission: AgentBashPermission = {
      enabled: true,
      rules: [{ pattern: 'rm -rf*', action: 'deny' }],
      default: 'allow',
    };
    expect(checkBashPermission('rm -rf /', permission)).toBe('deny');
  });

  it('无匹配时返回默认值', () => {
    const permission: AgentBashPermission = {
      enabled: true,
      rules: [],
      default: 'ask',
    };
    expect(checkBashPermission('npm install', permission)).toBe('ask');
  });

  it('规则优先级：先匹配的规则优先', () => {
    const permission: AgentBashPermission = {
      enabled: true,
      rules: [
        { pattern: 'git push --force*', action: 'deny' },
        { pattern: 'git push*', action: 'ask' },
      ],
      default: 'allow',
    };
    expect(checkBashPermission('git push --force origin', permission)).toBe('deny');
    expect(checkBashPermission('git push origin', permission)).toBe('ask');
  });
});

describe('checkFilePathPermission - 文件路径权限检查', () => {
  it('无敏感路径规则返回 null', () => {
    expect(checkFilePathPermission('/home/user/file.txt', undefined)).toBeNull();
    expect(checkFilePathPermission('/home/user/file.txt', [])).toBeNull();
  });

  it('匹配敏感路径规则', () => {
    const rules = [
      { pattern: '*.env', action: 'deny' as const },
      { pattern: '/etc/*', action: 'ask' as const },
    ];
    expect(checkFilePathPermission('.env', rules)).toBe('deny');
    expect(checkFilePathPermission('/etc/passwd', rules)).toBe('ask');
  });

  it('不匹配时返回 null', () => {
    const rules = [{ pattern: '*.env', action: 'deny' as const }];
    expect(checkFilePathPermission('config.json', rules)).toBeNull();
  });
});

describe('mergePermissions - 权限合并', () => {
  describe('优先级：Agent > Global > System', () => {
    it('Agent 配置覆盖 Global 和 System', () => {
      const system: AgentPermission = { file: { read: 'allow', write: 'ask' } };
      const global: AgentPermission = { file: { write: 'allow' } };
      const agent: AgentPermission = { file: { write: 'deny' } };

      const merged = mergePermissions(system, global, agent);
      expect(merged.file?.write).toBe('deny');
    });

    it('Global 配置覆盖 System', () => {
      const system: AgentPermission = { file: { write: 'ask' } };
      const global: AgentPermission = { file: { write: 'allow' } };

      const merged = mergePermissions(system, global, undefined);
      expect(merged.file?.write).toBe('allow');
    });

    it('无覆盖时使用 System 默认值', () => {
      const merged = mergePermissions(SYSTEM_DEFAULT_PERMISSION, undefined, undefined);
      expect(merged.file?.read).toBe('allow');
      expect(merged.file?.write).toBe('ask');
    });
  });

  describe('Bash 权限合并', () => {
    it('Agent 禁用 bash 覆盖全局', () => {
      const system: AgentPermission = { bash: { enabled: true } };
      const global: AgentPermission = { bash: { enabled: true } };
      const agent: AgentPermission = { bash: { enabled: false } };

      const merged = mergePermissions(system, global, agent);
      expect(merged.bash?.enabled).toBe(false);
    });

    it('Global 禁用 bash 且 Agent 未覆盖', () => {
      const system: AgentPermission = { bash: { enabled: true } };
      const global: AgentPermission = { bash: { enabled: false } };

      const merged = mergePermissions(system, global, undefined);
      expect(merged.bash?.enabled).toBe(false);
    });

    it('规则按优先级合并：Agent > Global > System', () => {
      const system: AgentPermission = {
        bash: { rules: [{ pattern: 'ls *', action: 'allow' }] },
      };
      const global: AgentPermission = {
        bash: { rules: [{ pattern: 'cat *', action: 'allow' }] },
      };
      const agent: AgentPermission = {
        bash: { rules: [{ pattern: 'rm *', action: 'deny' }] },
      };

      const merged = mergePermissions(system, global, agent);
      // Agent 规则在前
      expect(merged.bash?.rules?.[0].pattern).toBe('rm *');
      expect(merged.bash?.rules?.[1].pattern).toBe('cat *');
      expect(merged.bash?.rules?.[2].pattern).toBe('ls *');
    });
  });

  describe('Git 权限合并', () => {
    it('合并所有级别的 Git 权限', () => {
      const system: AgentPermission = { git: { read: 'allow', write: 'ask', dangerous: 'deny' } };
      const agent: AgentPermission = { git: { write: 'deny' } };

      const merged = mergePermissions(system, undefined, agent);
      expect(merged.git?.read).toBe('allow');    // 来自 system
      expect(merged.git?.write).toBe('deny');    // 来自 agent
      expect(merged.git?.dangerous).toBe('deny'); // 来自 system
    });
  });

  describe('Web 权限合并', () => {
    it('合并 Web 权限', () => {
      const system: AgentPermission = { web: 'ask' };
      const agent: AgentPermission = { web: 'deny' };

      const merged = mergePermissions(system, undefined, agent);
      expect(merged.web).toBe('deny');
    });
  });
});

describe('SYSTEM_DEFAULT_PERMISSION - 系统默认权限', () => {
  it('文件读取默认允许', () => {
    expect(SYSTEM_DEFAULT_PERMISSION.file?.read).toBe('allow');
  });

  it('文件写入默认询问', () => {
    expect(SYSTEM_DEFAULT_PERMISSION.file?.write).toBe('ask');
  });

  it('Bash 默认启用', () => {
    expect(SYSTEM_DEFAULT_PERMISSION.bash?.enabled).toBe(true);
  });

  it('包含安全命令白名单', () => {
    const rules = SYSTEM_DEFAULT_PERMISSION.bash?.rules ?? [];
    const lsRule = rules.find((r) => r.pattern === 'ls *');
    expect(lsRule?.action).toBe('allow');
  });

  it('包含危险命令黑名单', () => {
    const rules = SYSTEM_DEFAULT_PERMISSION.bash?.rules ?? [];
    const rmRule = rules.find((r) => r.pattern === 'rm -rf *');
    expect(rmRule?.action).toBe('deny');
  });

  it('Git 读取默认允许', () => {
    expect(SYSTEM_DEFAULT_PERMISSION.git?.read).toBe('allow');
  });

  it('Git 危险操作默认拒绝', () => {
    expect(SYSTEM_DEFAULT_PERMISSION.git?.dangerous).toBe('deny');
  });
});
