import { describe, it, expect, beforeEach, vi } from 'vitest';
import { WebPermissionChecker } from '../../../src/permission/checkers/web.js';

describe('WebPermissionChecker - Web 权限检查器', () => {
  let checker: WebPermissionChecker;

  beforeEach(() => {
    checker = new WebPermissionChecker();
  });

  describe('构造和基本属性', () => {
    it('有正确的名称', () => {
      expect(checker.name).toBe('web');
    });

    it('默认配置为 ask', () => {
      const config = checker.getConfig();
      expect(config.default).toBe('ask');
    });

    it('默认允许高级搜索', () => {
      const config = checker.getConfig();
      expect(config.allowAdvancedSearch).toBe(true);
    });
  });

  describe('checkWebPermission - 检查 Web 权限', () => {
    it('默认策略为 allow 时允许', async () => {
      checker.setConfig({ default: 'allow' });

      const result = await checker.checkWebPermission({ query: 'test search' });

      expect(result.allowed).toBe(true);
      expect(result.action).toBe('allow');
    });

    it('默认策略为 deny 时拒绝', async () => {
      checker.setConfig({ default: 'deny' });

      const result = await checker.checkWebPermission({ query: 'test search' });

      expect(result.allowed).toBe(false);
      expect(result.action).toBe('deny');
    });

    it('默认策略为 ask 时需要确认', async () => {
      checker.setConfig({ default: 'ask' });

      const result = await checker.checkWebPermission({ query: 'test search' });

      expect(result.allowed).toBe(false);
      expect(result.action).toBe('ask');
      expect(result.needsConfirmation).toBe(true);
    });

    it('不允许高级搜索时拒绝', async () => {
      checker.setConfig({ allowAdvancedSearch: false });

      const result = await checker.checkWebPermission({
        query: 'test search',
        searchDepth: 'advanced',
      });

      expect(result.allowed).toBe(false);
      expect(result.reason).toContain('不允许深度搜索');
    });

    it('主题不在允许列表时拒绝', async () => {
      checker.setConfig({ allowedTopics: ['general', 'news'] });

      const result = await checker.checkWebPermission({
        query: 'test search',
        topic: 'finance',
      });

      expect(result.allowed).toBe(false);
      expect(result.reason).toContain('不允许搜索主题');
    });

    it('主题在允许列表时通过', async () => {
      checker.setConfig({ default: 'allow', allowedTopics: ['general', 'news'] });

      const result = await checker.checkWebPermission({
        query: 'test search',
        topic: 'news',
      });

      expect(result.allowed).toBe(true);
    });

    it('空主题列表允许所有主题', async () => {
      checker.setConfig({ default: 'allow', allowedTopics: [] });

      const result = await checker.checkWebPermission({
        query: 'test search',
        topic: 'any-topic',
      });

      expect(result.allowed).toBe(true);
    });
  });

  describe('会话权限管理', () => {
    it('会话允许后不再询问', async () => {
      const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: true });
      checker.setAskCallback(mockCallback);

      // 第一次调用，触发回调
      const result1 = await checker.checkWebPermission({ query: 'test1' });
      expect(result1.allowed).toBe(true);
      expect(mockCallback).toHaveBeenCalledTimes(1);

      // 第二次调用，使用会话权限
      const result2 = await checker.checkWebPermission({ query: 'test2' });
      expect(result2.allowed).toBe(true);
      expect(mockCallback).toHaveBeenCalledTimes(1); // 不再调用
    });

    it('会话拒绝后不再询问', async () => {
      const mockCallback = vi.fn().mockResolvedValue({ allow: false, remember: true });
      checker.setAskCallback(mockCallback);

      // 第一次调用
      const result1 = await checker.checkWebPermission({ query: 'test1' });
      expect(result1.allowed).toBe(false);

      // 第二次调用
      const result2 = await checker.checkWebPermission({ query: 'test2' });
      expect(result2.allowed).toBe(false);
      expect(mockCallback).toHaveBeenCalledTimes(1);
    });

    it('不记住权限时每次询问', async () => {
      const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: false });
      checker.setAskCallback(mockCallback);

      await checker.checkWebPermission({ query: 'test1' });
      await checker.checkWebPermission({ query: 'test2' });

      expect(mockCallback).toHaveBeenCalledTimes(2);
    });

    it('清除会话权限后重新询问', async () => {
      const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: true });
      checker.setAskCallback(mockCallback);

      await checker.checkWebPermission({ query: 'test1' });
      checker.clearSessionPermissions();
      await checker.checkWebPermission({ query: 'test2' });

      expect(mockCallback).toHaveBeenCalledTimes(2);
    });
  });

  describe('check - 通用接口', () => {
    it('从 command 中提取查询', async () => {
      checker.setConfig({ default: 'allow' });

      const result = await checker.check({
        command: 'web_search: test query',
        workdir: '/test',
      });

      expect(result.allowed).toBe(true);
    });
  });

  describe('配置管理', () => {
    it('getConfig 返回配置副本', () => {
      const config1 = checker.getConfig();
      config1.default = 'deny';

      const config2 = checker.getConfig();
      expect(config2.default).toBe('ask'); // 原配置不变
    });

    it('setConfig 部分更新配置', () => {
      checker.setConfig({ allowAdvancedSearch: false });

      const config = checker.getConfig();
      expect(config.allowAdvancedSearch).toBe(false);
      expect(config.default).toBe('ask'); // 其他配置不变
    });
  });
});
