import { describe, it, expect } from 'vitest';
import { z } from 'zod';
import { buildZodSchema, type ToolParameter } from '../../../src/types/index.js';

describe('buildZodSchema', () => {
  describe('基本类型转换', () => {
    it('转换 string 类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        name: {
          type: 'string',
          description: '用户名',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);
      expect(schema.shape.name).toBeDefined();

      // 验证 schema 可以正确解析
      const result = schema.safeParse({ name: 'test' });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.name).toBe('test');
      }
    });

    it('转换 number 类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        age: {
          type: 'number',
          description: '年龄',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      const result = schema.safeParse({ age: 25 });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.age).toBe(25);
      }

      // 字符串应该失败
      const invalidResult = schema.safeParse({ age: '25' });
      expect(invalidResult.success).toBe(false);
    });

    it('转换 boolean 类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        active: {
          type: 'boolean',
          description: '是否激活',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      expect(schema.safeParse({ active: true }).success).toBe(true);
      expect(schema.safeParse({ active: false }).success).toBe(true);
      expect(schema.safeParse({ active: 'true' }).success).toBe(false);
    });

    it('转换 array 类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        items: {
          type: 'array',
          description: '项目列表',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      const result = schema.safeParse({ items: [1, 'two', { three: 3 }] });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.items).toEqual([1, 'two', { three: 3 }]);
      }
    });

    it('转换 object 类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        config: {
          type: 'object',
          description: '配置对象',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      const result = schema.safeParse({ config: { key: 'value', nested: { a: 1 } } });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.config).toEqual({ key: 'value', nested: { a: 1 } });
      }
    });

    it('处理未知类型为 unknown', () => {
      const parameters = {
        data: {
          type: 'custom' as any,
          description: '自定义类型',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      // unknown 类型接受任何值
      expect(schema.safeParse({ data: 'anything' }).success).toBe(true);
      expect(schema.safeParse({ data: 123 }).success).toBe(true);
      expect(schema.safeParse({ data: { obj: true } }).success).toBe(true);
    });
  });

  describe('可选参数', () => {
    it('required=false 时参数可选', () => {
      const parameters: Record<string, ToolParameter> = {
        optional_field: {
          type: 'string',
          description: '可选字段',
          required: false,
        },
      };

      const schema = buildZodSchema(parameters);

      // 不提供可选字段应该成功
      expect(schema.safeParse({}).success).toBe(true);

      // 提供可选字段也应该成功
      expect(schema.safeParse({ optional_field: 'value' }).success).toBe(true);
    });

    it('required 未设置时默认可选', () => {
      const parameters: Record<string, ToolParameter> = {
        field: {
          type: 'string',
          description: '字段',
          // required 未设置
        },
      };

      const schema = buildZodSchema(parameters);

      // 应该是可选的
      expect(schema.safeParse({}).success).toBe(true);
    });

    it('required=true 时参数必须', () => {
      const parameters: Record<string, ToolParameter> = {
        required_field: {
          type: 'string',
          description: '必填字段',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      // 不提供必填字段应该失败
      expect(schema.safeParse({}).success).toBe(false);

      // 提供必填字段应该成功
      expect(schema.safeParse({ required_field: 'value' }).success).toBe(true);
    });
  });

  describe('混合参数', () => {
    it('处理多个混合类型参数', () => {
      const parameters: Record<string, ToolParameter> = {
        path: {
          type: 'string',
          description: '文件路径',
          required: true,
        },
        line_number: {
          type: 'number',
          description: '行号',
          required: false,
        },
        recursive: {
          type: 'boolean',
          description: '递归处理',
          required: false,
        },
        patterns: {
          type: 'array',
          description: '模式列表',
          required: false,
        },
        options: {
          type: 'object',
          description: '额外选项',
          required: false,
        },
      };

      const schema = buildZodSchema(parameters);

      // 只提供必填参数
      expect(schema.safeParse({ path: '/test/file.txt' }).success).toBe(true);

      // 提供所有参数
      const fullResult = schema.safeParse({
        path: '/test/file.txt',
        line_number: 42,
        recursive: true,
        patterns: ['*.ts', '*.js'],
        options: { encoding: 'utf-8' },
      });
      expect(fullResult.success).toBe(true);
    });

    it('空参数对象返回空 schema', () => {
      const parameters: Record<string, ToolParameter> = {};

      const schema = buildZodSchema(parameters);

      expect(schema.safeParse({}).success).toBe(true);
      expect(Object.keys(schema.shape)).toHaveLength(0);
    });
  });

  describe('描述信息', () => {
    it('保留参数描述', () => {
      const parameters: Record<string, ToolParameter> = {
        message: {
          type: 'string',
          description: '要发送的消息内容',
          required: true,
        },
      };

      const schema = buildZodSchema(parameters);

      // 验证 schema 被正确创建
      expect(schema.shape.message).toBeDefined();

      // 验证 schema 可以正常工作
      const result = schema.safeParse({ message: 'test' });
      expect(result.success).toBe(true);
    });
  });

  describe('实际工具参数示例', () => {
    it('bash 工具参数', () => {
      const bashParameters: Record<string, ToolParameter> = {
        command: {
          type: 'string',
          description: '要执行的 bash 命令',
          required: true,
        },
        timeout: {
          type: 'number',
          description: '超时时间（毫秒）',
          required: false,
        },
      };

      const schema = buildZodSchema(bashParameters);

      expect(schema.safeParse({ command: 'ls -la' }).success).toBe(true);
      expect(schema.safeParse({ command: 'ls -la', timeout: 5000 }).success).toBe(true);
      expect(schema.safeParse({}).success).toBe(false);
    });

    it('read_file 工具参数', () => {
      const readFileParameters: Record<string, ToolParameter> = {
        path: {
          type: 'string',
          description: '文件路径',
          required: true,
        },
        encoding: {
          type: 'string',
          description: '文件编码',
          required: false,
        },
      };

      const schema = buildZodSchema(readFileParameters);

      expect(schema.safeParse({ path: '/etc/hosts' }).success).toBe(true);
      expect(schema.safeParse({ path: '/etc/hosts', encoding: 'utf-8' }).success).toBe(true);
    });

    it('write_file 工具参数', () => {
      const writeFileParameters: Record<string, ToolParameter> = {
        path: {
          type: 'string',
          description: '文件路径',
          required: true,
        },
        content: {
          type: 'string',
          description: '文件内容',
          required: true,
        },
        create_dirs: {
          type: 'boolean',
          description: '自动创建目录',
          required: false,
        },
      };

      const schema = buildZodSchema(writeFileParameters);

      expect(schema.safeParse({ path: '/tmp/test.txt', content: 'hello' }).success).toBe(true);
      expect(schema.safeParse({ path: '/tmp/test.txt', content: 'hello', create_dirs: true }).success).toBe(true);
      expect(schema.safeParse({ path: '/tmp/test.txt' }).success).toBe(false);
    });

    it('task 工具参数', () => {
      const taskParameters: Record<string, ToolParameter> = {
        description: {
          type: 'string',
          description: '任务描述',
          required: true,
        },
        prompt: {
          type: 'string',
          description: '任务提示',
          required: true,
        },
        subagent_type: {
          type: 'string',
          description: 'Agent 类型',
          required: true,
        },
        run_in_background: {
          type: 'boolean',
          description: '是否后台运行',
          required: false,
        },
        images: {
          type: 'array',
          description: '图片数据',
          required: false,
        },
      };

      const schema = buildZodSchema(taskParameters);

      expect(schema.safeParse({
        description: 'Test task',
        prompt: 'Do something',
        subagent_type: 'explore',
      }).success).toBe(true);

      expect(schema.safeParse({
        description: 'Vision task',
        prompt: 'Analyze image',
        subagent_type: 'vision',
        images: [{ data: 'base64...', mimeType: 'image/png' }],
      }).success).toBe(true);
    });
  });
});
