/**
 * Agents Route 测试
 *
 * 测试 Agent 预设管理 REST API 端点
 */

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { Hono } from 'hono';

// Create mock agent module
const mockAgentRegistry = vi.hoisted(() => ({
  init: vi.fn().mockResolvedValue(undefined),
  get: vi.fn(),
  list: vi.fn(),
}));

const mockPresetAgents = vi.hoisted(() => ({
  general: {
    description: 'General purpose agent',
    mode: 'subagent' as const,
    model: { model: 'claude-3-5-sonnet' },
  },
  explore: {
    description: 'Code exploration agent',
    mode: 'subagent' as const,
  },
}));

const mockAgentModule = vi.hoisted(() => ({
  agentRegistry: mockAgentRegistry,
  loadAgentConfig: vi.fn(),
  saveAgentConfig: vi.fn(),
  presetAgents: mockPresetAgents,
  isPresetAgent: vi.fn((name: string) => name in mockPresetAgents),
}));

// Track if module should be available
let moduleAvailable = true;

vi.mock('@ai-assistant/core', () => {
  if (!moduleAvailable) {
    throw new Error('Module not found');
  }
  return mockAgentModule;
});

vi.mock('../../../src/routes/config.js', () => ({
  getConfig: vi.fn(() => ({ workdir: '/test/workdir' })),
}));

import { agentsRouter } from '../../../src/routes/agents.js';

// Create test app
const app = new Hono();
app.route('/agents', agentsRouter);

describe('Agents Route', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    moduleAvailable = true;
    mockAgentModule.loadAgentConfig.mockResolvedValue(null);
    mockAgentModule.saveAgentConfig.mockResolvedValue(undefined);
  });

  describe('GET /agents - 获取所有 Agent 列表', () => {
    it('返回 Agent 列表', async () => {
      mockAgentRegistry.list.mockReturnValue([
        { name: 'general', description: 'General purpose agent', mode: 'subagent' },
        { name: 'explore', description: 'Code exploration agent', mode: 'subagent' },
      ]);

      const res = await app.request('/agents');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(json.data).toHaveLength(2);
      expect(json.data[0].name).toBe('general');
    });

    it('返回空列表', async () => {
      mockAgentRegistry.list.mockReturnValue([]);

      const res = await app.request('/agents');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.data).toEqual([]);
    });

    it('包含 isPreset 和 isCustomized 标记', async () => {
      mockAgentRegistry.list.mockReturnValue([
        { name: 'general', description: 'General purpose agent', mode: 'subagent' },
      ]);
      mockAgentModule.loadAgentConfig.mockResolvedValue({
        agents: { general: { model: { model: 'custom-model' } } },
      });

      const res = await app.request('/agents');
      const json = await res.json();

      expect(json.data[0].isPreset).toBe(true);
      expect(json.data[0].isCustomized).toBe(true);
    });
  });

  describe('GET /agents/presets - 获取预设 Agent 列表', () => {
    it('返回预设列表', async () => {
      const res = await app.request('/agents/presets');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(json.data).toHaveLength(2);
      expect(json.data.some((a: { name: string }) => a.name === 'general')).toBe(true);
      expect(json.data.some((a: { name: string }) => a.name === 'explore')).toBe(true);
    });

    it('预设都标记为 isPreset: true', async () => {
      const res = await app.request('/agents/presets');
      const json = await res.json();

      expect(json.data.every((a: { isPreset: boolean }) => a.isPreset === true)).toBe(true);
    });
  });

  describe('GET /agents/defaults - 获取全局默认配置', () => {
    it('返回默认配置', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue({
        defaults: {
          maxSteps: 10,
          model: { model: 'claude-3-5-sonnet' },
        },
      });

      const res = await app.request('/agents/defaults');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(json.data.maxSteps).toBe(10);
    });

    it('无配置时返回空对象', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue(null);

      const res = await app.request('/agents/defaults');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.data).toEqual({});
    });
  });

  describe('PUT /agents/defaults - 更新全局默认配置', () => {
    it('更新成功', async () => {
      const res = await app.request('/agents/defaults', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ maxSteps: 20 }),
      });
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(mockAgentModule.saveAgentConfig).toHaveBeenCalled();
    });
  });

  describe('GET /agents/:name - 获取单个 Agent 详情', () => {
    it('返回 Agent 详情', async () => {
      mockAgentRegistry.get.mockReturnValue({
        name: 'general',
        description: 'General purpose agent',
        mode: 'subagent',
      });

      const res = await app.request('/agents/general');
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(json.data.name).toBe('general');
      expect(json.data.isPreset).toBe(true);
    });

    it('Agent 不存在返回 404', async () => {
      mockAgentRegistry.get.mockReturnValue(undefined);

      const res = await app.request('/agents/non-existent');
      const json = await res.json();

      expect(res.status).toBe(404);
      expect(json.success).toBe(false);
      expect(json.error).toContain('not found');
    });
  });

  describe('POST /agents - 创建新 Agent', () => {
    it('创建成功', async () => {
      mockAgentRegistry.get.mockReturnValue({
        name: 'my-agent',
        description: 'My custom agent',
        mode: 'subagent',
      });

      const res = await app.request('/agents', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: 'my-agent',
          description: 'My custom agent',
          mode: 'subagent',
        }),
      });
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(mockAgentModule.saveAgentConfig).toHaveBeenCalled();
    });

    it('缺少名称返回 400', async () => {
      const res = await app.request('/agents', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ description: 'No name agent' }),
      });
      const json = await res.json();

      expect(res.status).toBe(400);
      expect(json.success).toBe(false);
      expect(json.error).toContain('name is required');
    });

    it('名称与预设冲突返回 400', async () => {
      const res = await app.request('/agents', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: 'general',
          description: 'Trying to create preset',
          mode: 'subagent',
        }),
      });
      const json = await res.json();

      expect(res.status).toBe(400);
      expect(json.error).toContain('preset name');
    });

    it('Agent 已存在返回 409', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue({
        agents: { 'my-agent': { description: 'Existing' } },
      });

      const res = await app.request('/agents', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: 'my-agent',
          description: 'Duplicate',
          mode: 'subagent',
        }),
      });
      const json = await res.json();

      expect(res.status).toBe(409);
      expect(json.error).toContain('already exists');
    });
  });

  describe('PUT /agents/:name - 更新 Agent', () => {
    it('更新成功', async () => {
      mockAgentRegistry.get.mockReturnValue({
        name: 'general',
        description: 'Updated description',
        mode: 'subagent',
      });

      const res = await app.request('/agents/general', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          description: 'Updated description',
          mode: 'subagent',
        }),
      });
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(json.data.isCustomized).toBe(true);
    });
  });

  describe('DELETE /agents/:name - 删除 Agent', () => {
    it('删除自定义 Agent 成功', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue({
        agents: { 'my-agent': { description: 'Custom agent' } },
      });

      const res = await app.request('/agents/my-agent', {
        method: 'DELETE',
      });
      const json = await res.json();

      expect(res.status).toBe(200);
      expect(json.success).toBe(true);
      expect(mockAgentModule.saveAgentConfig).toHaveBeenCalled();
    });

    it('删除预设 Agent 返回 400', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue({ agents: {} });

      const res = await app.request('/agents/general', {
        method: 'DELETE',
      });
      const json = await res.json();

      expect(res.status).toBe(400);
      expect(json.error).toContain('Cannot delete preset');
    });

    it('Agent 不存在返回 404', async () => {
      mockAgentModule.loadAgentConfig.mockResolvedValue({ agents: {} });
      mockAgentModule.isPresetAgent.mockReturnValue(false);

      const res = await app.request('/agents/non-existent', {
        method: 'DELETE',
      });
      const json = await res.json();

      expect(res.status).toBe(404);
      expect(json.error).toContain('not found');
    });
  });
});
