import { describe, it, expect, beforeEach, vi } from 'vitest';
import { skillTool, updateSkillDescription } from '../../../../src/tools/skill/skill.js';
import { getSkillRegistry, resetSkillRegistry } from '../../../../src/skills/registry.js';
import type { Skill } from '../../../../src/skills/types.js';

// Mock loader to prevent file system access
vi.mock('../../../../src/skills/loader.js', () => ({
  skillLoader: {
    loadFromDirectory: vi.fn().mockResolvedValue([]),
    getUserSkillsDir: vi.fn().mockReturnValue('/mock/user/skills'),
    getProjectSkillsDir: vi.fn().mockReturnValue('/mock/project/skills'),
  },
}));

// Mock builtin skills
vi.mock('../../../../src/skills/builtin/index.js', () => ({
  builtinSkills: [
    {
      name: 'code-review',
      description: '代码审查',
      promptTemplate: '请审查以下代码：\n\n{{code}}\n\n重点：{{focus}}',
      parameters: {
        code: { type: 'string', required: true, description: '代码' },
        focus: { type: 'string', required: false, default: '代码质量', description: '审查重点' },
      },
      category: 'development',
      source: 'builtin',
      enabled: true,
    },
    {
      name: 'disabled-skill',
      description: '禁用的 Skill',
      promptTemplate: '不应该执行',
      source: 'builtin',
      enabled: false,
    },
  ],
}));

describe('skillTool - Skill 工具', () => {
  beforeEach(async () => {
    vi.clearAllMocks();
    resetSkillRegistry();
    // 初始化注册表
    const registry = getSkillRegistry();
    await registry.initialize();
  });

  describe('工具定义', () => {
    it('有正确的名称', () => {
      expect(skillTool.name).toBe('skill');
    });

    it('有正确的元数据', () => {
      expect(skillTool.metadata.category).toBe('agent');
      expect(skillTool.metadata.keywords).toContain('skill');
    });

    it('skill_name 参数是必须的', () => {
      expect(skillTool.parameters.skill_name.required).toBe(true);
    });

    it('params 参数是可选的', () => {
      expect(skillTool.parameters.params.required).toBe(false);
    });
  });

  describe('execute - 执行', () => {
    it('成功执行 Skill 并渲染模板', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-review',
        params: {
          code: 'function add(a, b) { return a + b; }',
          focus: '性能',
        },
      });

      expect(result.success).toBe(true);
      expect(result.output).toContain('function add');
      expect(result.output).toContain('性能');
      expect(result.metadata?.skill).toBe('code-review');
    });

    it('使用默认参数值', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-review',
        params: {
          code: 'const x = 1;',
        },
      });

      expect(result.success).toBe(true);
      expect(result.output).toContain('代码质量'); // 默认值
    });

    it('Skill 不存在时返回错误', async () => {
      const result = await skillTool.execute({
        skill_name: 'non-existent',
        params: {},
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('不存在');
    });

    it('Skill 不存在时提供建议', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-rev', // 类似 code-review
        params: {},
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('code-review'); // 建议
    });

    it('缺少必需参数时返回错误', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-review',
        params: {}, // 缺少 code 参数
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('缺少必需参数');
    });

    it('禁用的 Skill 返回错误', async () => {
      const result = await skillTool.execute({
        skill_name: 'disabled-skill',
        params: {},
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('禁用');
    });

    it('返回正确的 metadata', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-review',
        params: { code: 'test' },
      });

      expect(result.metadata?.skill).toBe('code-review');
      expect(result.metadata?.category).toBe('development');
      expect(result.metadata?.source).toBe('builtin');
    });
  });

  describe('工具描述', () => {
    it('更新后描述包含可用 Skill 列表', () => {
      // beforeEach 中已初始化 registry，现在更新描述
      updateSkillDescription();

      expect(skillTool.description).toContain('code-review');
      expect(skillTool.description).toContain('代码审查');
    });

    it('更新后描述包含分类信息', () => {
      updateSkillDescription();
      expect(skillTool.description).toContain('[development]');
    });

    it('更新后描述包含使用示例', () => {
      updateSkillDescription();
      expect(skillTool.description).toContain('使用示例');
      expect(skillTool.description).toContain('skill_name');
    });

    it('禁用的 Skill 不在描述中', () => {
      updateSkillDescription();
      expect(skillTool.description).not.toContain('disabled-skill');
    });
  });

  describe('updateSkillDescription', () => {
    it('调用后描述被更新', async () => {
      updateSkillDescription();

      // 描述应该包含当前注册的 Skill
      expect(skillTool.description).toContain('code-review');
      expect(typeof skillTool.description).toBe('string');
    });
  });

  describe('边界情况', () => {
    it('params 为 undefined 时使用空对象', async () => {
      const result = await skillTool.execute({
        skill_name: 'code-review',
        // 不提供 params
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('缺少必需参数');
    });

    it('skill_name 为空字符串时返回错误', async () => {
      const result = await skillTool.execute({
        skill_name: '',
        params: {},
      });

      expect(result.success).toBe(false);
      expect(result.error).toContain('不存在');
    });
  });
});
