import { describe, it, expect } from 'vitest';
import {
  renderTemplate,
  renderPromptTemplate,
  createToolDescriptionContext,
} from '../../../src/template/renderer.js';
import type { ExtendedTemplateContext } from '../../../src/template/types.js';
import {
  CUSTOM_TIMEOUT_MS,
  MAX_TIMEOUT_MS,
  MAX_OUTPUT_CHARS,
} from '../../../src/constants/bash-tool.js';

describe('Template Renderer - 模板渲染器', () => {
  describe('基础变量替换', () => {
    it('替换简单变量', () => {
      const result = renderTemplate('Hello ${name}!', { name: 'World' });
      expect(result).toBe('Hello World!');
    });

    it('替换嵌套属性', () => {
      const result = renderTemplate('${user.name} is ${user.age}', {
        user: { name: 'Alice', age: 30 },
      });
      expect(result).toBe('Alice is 30');
    });

    it('处理未定义变量 - 默认空字符串', () => {
      const result = renderTemplate('Value: ${undefined_var}', {});
      expect(result).toBe('Value: ');
    });

    it('处理未定义变量 - 自定义默认值', () => {
      const result = renderTemplate('Value: ${undefined_var}', {}, { undefinedValue: 'N/A' });
      expect(result).toBe('Value: N/A');
    });
  });

  describe('三元表达式', () => {
    it('条件为真时返回 trueValue', () => {
      const result = renderTemplate('${isActive ? "Active" : "Inactive"}', { isActive: true });
      expect(result).toBe('Active');
    });

    it('条件为假时返回 falseValue', () => {
      const result = renderTemplate('${isActive ? "Active" : "Inactive"}', { isActive: false });
      expect(result).toBe('Inactive');
    });

    it('空字符串被视为假', () => {
      const result = renderTemplate('${value ? "yes" : "no"}', { value: '' });
      expect(result).toBe('no');
    });
  });

  describe('函数调用', () => {
    it('调用注册的函数', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {
          GET_VALUE: () => 42,
        },
      };
      const result = renderTemplate('Value: ${GET_VALUE()}', context);
      expect(result).toBe('Value: 42');
    });

    it('调用返回字符串的函数', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {
          GET_MESSAGE: () => 'Hello from function',
        },
      };
      const result = renderTemplate('${GET_MESSAGE()}', context);
      expect(result).toBe('Hello from function');
    });

    it('未注册的函数返回空字符串', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {},
      };
      const result = renderTemplate('Value: ${UNKNOWN_FUNC()}', context);
      expect(result).toBe('Value: ');
    });

    it('没有 __functions__ 时返回空字符串', () => {
      const result = renderTemplate('Value: ${SOME_FUNC()}', {});
      expect(result).toBe('Value: ');
    });
  });

  describe('算术运算（除法）', () => {
    it('数值除法', () => {
      const result = renderTemplate('${value / 1000}', { value: 60000 });
      expect(result).toBe('60');
    });

    it('函数调用结果除法', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {
          GET_MS: () => 120000,
        },
      };
      const result = renderTemplate('${GET_MS() / 60000} minutes', context);
      expect(result).toBe('2 minutes');
    });

    it('结果向下取整', () => {
      const result = renderTemplate('${value / 1000}', { value: 12345 });
      expect(result).toBe('12');
    });

    it('除以零不进行除法运算', () => {
      // 除以零时，divMatch 匹配但 divisor === 0，会跳过除法逻辑
      // 然后尝试作为变量处理 "value / 0"，找不到返回空
      const result = renderTemplate('${value / 0}', { value: 100 });
      expect(result).toBe('');
    });
  });

  describe('组合表达式', () => {
    it('函数调用 + 除法 + 字符串', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {
          TIMEOUT_MS: () => 600000,
        },
      };
      const result = renderTemplate(
        'Timeout: ${TIMEOUT_MS()}ms (${TIMEOUT_MS()/60000} minutes)',
        context
      );
      expect(result).toBe('Timeout: 600000ms (10 minutes)');
    });

    it('多个函数调用', () => {
      const context: ExtendedTemplateContext = {
        __functions__: {
          MIN_VAL: () => 10,
          MAX_VAL: () => 100,
        },
      };
      const result = renderTemplate('Range: ${MIN_VAL()} - ${MAX_VAL()}', context);
      expect(result).toBe('Range: 10 - 100');
    });

    it('函数调用 + 变量混合', () => {
      const context: ExtendedTemplateContext = {
        toolName: 'bash',
        __functions__: {
          GET_TIMEOUT: () => 120000,
        },
      };
      const result = renderTemplate(
        'Use ${toolName} with timeout ${GET_TIMEOUT()}ms',
        context
      );
      expect(result).toBe('Use bash with timeout 120000ms');
    });
  });
});

describe('createToolDescriptionContext - 工具描述上下文', () => {
  it('包含工具名称变量', () => {
    const context = createToolDescriptionContext();
    expect(context.custom?.BASH_TOOL_NAME).toBe('bash');
    expect(context.custom?.GREP_TOOL_NAME).toBe('grep');
    expect(context.custom?.GLOB_TOOL_NAME).toBe('glob');
  });

  it('包含注册的模板函数', () => {
    const context = createToolDescriptionContext();
    expect(context.__functions__).toBeDefined();
    expect(typeof context.__functions__.CUSTOM_TIMEOUT_MS).toBe('function');
    expect(typeof context.__functions__.MAX_TIMEOUT_MS).toBe('function');
    expect(typeof context.__functions__.MAX_OUTPUT_CHARS).toBe('function');
  });

  it('函数返回正确的配置值', () => {
    const context = createToolDescriptionContext();
    expect(context.__functions__.CUSTOM_TIMEOUT_MS()).toBe(CUSTOM_TIMEOUT_MS);
    expect(context.__functions__.MAX_TIMEOUT_MS()).toBe(MAX_TIMEOUT_MS);
    expect(context.__functions__.MAX_OUTPUT_CHARS()).toBe(MAX_OUTPUT_CHARS);
  });
});

describe('renderPromptTemplate - 提示词模板渲染', () => {
  it('渲染带函数调用的模板', () => {
    const context = createToolDescriptionContext();
    const template = 'Timeout: ${CUSTOM_TIMEOUT_MS()}ms (${CUSTOM_TIMEOUT_MS()/60000} minutes)';
    const result = renderPromptTemplate(template, context);
    expect(result).toBe(`Timeout: ${CUSTOM_TIMEOUT_MS}ms (${Math.floor(CUSTOM_TIMEOUT_MS / 60000)} minutes)`);
  });

  it('渲染带工具名变量的模板', () => {
    const context = createToolDescriptionContext();
    const template = 'Use ${BASH_TOOL_NAME} or ${GREP_TOOL_NAME}';
    const result = renderPromptTemplate(template, context);
    expect(result).toBe('Use bash or grep');
  });

  it('渲染完整的 bash 描述模板片段', () => {
    const context = createToolDescriptionContext();
    const template = `Commands timeout after \${MAX_TIMEOUT_MS()}ms (\${MAX_TIMEOUT_MS()/60000} minutes).
Output truncated at \${MAX_OUTPUT_CHARS()} chars.
Use \${GREP_TOOL_NAME} for search.`;

    const result = renderPromptTemplate(template, context);

    expect(result).toContain(`${MAX_TIMEOUT_MS}ms`);
    expect(result).toContain(`${Math.floor(MAX_TIMEOUT_MS / 60000)} minutes`);
    expect(result).toContain(`${MAX_OUTPUT_CHARS} chars`);
    expect(result).toContain('grep for search');
  });
});

describe('回归测试 - 确保现有功能正常', () => {
  it('字符串字面量中的变量插值', () => {
    const result = renderTemplate('${cond ? "Value is ${val}" : "No value"}', {
      cond: true,
      val: 42,
    });
    expect(result).toBe('Value is 42');
  });

  it('布尔值处理', () => {
    expect(renderTemplate('${flag}', { flag: true })).toBe('true');
    expect(renderTemplate('${flag}', { flag: false })).toBe('');
  });

  it('数字值处理', () => {
    expect(renderTemplate('${num}', { num: 123 })).toBe('123');
    expect(renderTemplate('${num}', { num: 0 })).toBe('0');
  });

  it('嵌套对象访问', () => {
    const result = renderTemplate('${a.b.c}', { a: { b: { c: 'deep' } } });
    expect(result).toBe('deep');
  });

  it('多个模板变量', () => {
    const result = renderTemplate('${a} + ${b} = ${c}', { a: 1, b: 2, c: 3 });
    expect(result).toBe('1 + 2 = 3');
  });
});
