/**
 * Commands API Routes
 *
 * 提供斜杠命令的 REST API，支持列出、查询、执行和重载命令
 */

import { Hono } from 'hono';
import { z } from 'zod';
import { getConfig } from './config.js';

// Zod schemas
const ExecuteCommandInputSchema = z.object({
  arguments: z.string().default(''),
});

const SearchCommandInputSchema = z.object({
  query: z.string().min(1),
  limit: z.number().int().min(1).max(50).default(10),
});

export const commandsRouter = new Hono();

// Zod schemas for CRUD
const CreateCommandInputSchema = z.object({
  name: z.string().min(1),
  description: z.string().optional(),
  template: z.string().min(1),
  agent: z.string().optional(),
  model: z.string().optional(),
  subtask: z.boolean().optional(),
  scope: z.enum(['user', 'project']),
});

const UpdateCommandInputSchema = z.object({
  description: z.string().optional(),
  template: z.string().optional(),
  agent: z.string().optional(),
  model: z.string().optional(),
  subtask: z.boolean().optional(),
});

// Core 模块类型
interface CommandModule {
  getCommandRegistry: () => CommandRegistry;
  createCommandExecutor: (workdir: string) => CommandExecutor;
  createCommandManager: (workdir: string) => CommandManager;
}

interface CommandRegistry {
  initialize(workdir: string): Promise<void>;
  reload(workdir: string): Promise<void>;
  get(name: string): Command | undefined;
  getAll(): Command[];
  list(): Array<{ name: string; description?: string; source: string }>;
  search(query: string, limit?: number): Array<{ command: Command; score: number }>;
  getStats(): { total: number; bySource: Record<string, number> };
}

interface CommandExecutor {
  execute(input: CommandInput): Promise<CommandExecutionResult>;
}

interface Command {
  name: string;
  description?: string;
  template: string;
  agent?: string;
  model?: string;
  subtask?: boolean;
  source: 'builtin' | 'user' | 'project';
  sourcePath?: string;
}

interface CommandInput {
  command: string;
  arguments: string;
  args: string[];
  workdir: string;
}

interface CommandExecutionResult {
  success: boolean;
  prompt?: string;
  agent?: string;
  model?: string;
  subtask?: boolean;
  error?: string;
}

interface CommandManager {
  create(input: {
    name: string;
    description?: string;
    template: string;
    agent?: string;
    model?: string;
    subtask?: boolean;
    scope: 'user' | 'project';
  }): Promise<{ success: boolean; path?: string; error?: string }>;
  update(
    name: string,
    input: {
      description?: string;
      template?: string;
      agent?: string;
      model?: string;
      subtask?: boolean;
    }
  ): Promise<{ success: boolean; path?: string; error?: string }>;
  delete(name: string): Promise<{ success: boolean; path?: string; error?: string }>;
  getContent(name: string): Promise<{
    success: boolean;
    data?: {
      name: string;
      description?: string;
      template: string;
      agent?: string;
      model?: string;
      subtask?: boolean;
      source: string;
      sourcePath?: string;
    };
    error?: string;
  }>;
}

// Core 模块缓存
let commandModule: CommandModule | null = null;

/**
 * 初始化 Command 模块
 */
async function initCommandModule(): Promise<CommandModule | null> {
  if (commandModule) return commandModule;

  try {
    const corePath = '@ai-assistant/core';
    const core = (await import(corePath)) as Record<string, unknown>;

    if (
      typeof core.getCommandRegistry !== 'function' ||
      typeof core.createCommandExecutor !== 'function' ||
      typeof core.createCommandManager !== 'function'
    ) {
      console.warn('[Commands] Core module missing command exports');
      return null;
    }

    commandModule = {
      getCommandRegistry: core.getCommandRegistry as () => CommandRegistry,
      createCommandExecutor: core.createCommandExecutor as (workdir: string) => CommandExecutor,
      createCommandManager: core.createCommandManager as (workdir: string) => CommandManager,
    };

    // Initialize registry with server workdir
    const config = getConfig();
    const registry = commandModule.getCommandRegistry();
    await registry.initialize(config.workdir);

    console.log('[Commands] Command module initialized');
    return commandModule;
  } catch (error) {
    console.warn('[Commands] Failed to load core module:', error);
    return null;
  }
}

/**
 * GET /commands - 列出所有命令
 */
commandsRouter.get('/', async (c) => {
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  const registry = module.getCommandRegistry();

  return c.json({
    success: true,
    data: {
      commands: registry.list(),
      stats: registry.getStats(),
    },
  });
});

/**
 * POST /commands/search - 搜索命令
 * 注意：这个路由必须在 /:name 之前定义，否则会被匹配为命令名
 */
commandsRouter.post('/search', async (c) => {
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json();
    const input = SearchCommandInputSchema.parse(body);

    const registry = module.getCommandRegistry();
    const results = registry.search(input.query, input.limit);

    return c.json({
      success: true,
      data: results.map(({ command, score }) => ({
        name: command.name,
        description: command.description,
        source: command.source,
        score,
      })),
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Invalid input',
      },
      400
    );
  }
});

/**
 * POST /commands/reload - 重新加载命令
 */
commandsRouter.post('/reload', async (c) => {
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  try {
    const config = getConfig();
    const registry = module.getCommandRegistry();
    await registry.reload(config.workdir);

    return c.json({
      success: true,
      data: {
        message: 'Commands reloaded',
        stats: registry.getStats(),
      },
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Reload failed',
      },
      500
    );
  }
});

/**
 * POST /commands/:name/execute - 执行命令（渲染模板）
 * 注意：带后缀的路由必须在 /:name{.+} 之前定义，否则会被 {.+} 匹配
 */
commandsRouter.post('/:name{.+}/execute', async (c) => {
  const name = c.req.param('name');
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json().catch(() => ({}));
    const input = ExecuteCommandInputSchema.parse(body);

    const config = getConfig();
    const executor = module.createCommandExecutor(config.workdir);

    // Parse arguments
    const args = input.arguments ? input.arguments.split(/\s+/).filter(Boolean) : [];

    const result = await executor.execute({
      command: name,
      arguments: input.arguments,
      args,
      workdir: config.workdir,
    });

    return c.json(
      {
        success: result.success,
        data: result.success
          ? {
              prompt: result.prompt,
              agent: result.agent,
              model: result.model,
              subtask: result.subtask,
            }
          : undefined,
        error: result.error,
      },
      result.success ? 200 : 400
    );
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Invalid input',
      },
      400
    );
  }
});

/**
 * GET /commands/:name/content - 获取命令完整内容（包含 template）
 * 注意：带后缀的路由必须在 /:name{.+} 之前定义，否则会被 {.+} 匹配
 */
commandsRouter.get('/:name{.+}/content', async (c) => {
  const name = c.req.param('name');
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  const config = getConfig();
  const manager = module.createCommandManager(config.workdir);
  const result = await manager.getContent(name);

  if (result.success) {
    return c.json({
      success: true,
      data: result.data,
    });
  } else {
    return c.json(
      {
        success: false,
        error: result.error,
      },
      404
    );
  }
});

/**
 * GET /commands/:name - 获取命令详情
 * 使用 {.+} 匹配包含 / 的命令名（如 deploy/staging）
 * 注意：这个通用路由必须在所有带后缀的路由之后定义
 */
commandsRouter.get('/:name{.+}', async (c) => {
  const name = c.req.param('name');
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  const registry = module.getCommandRegistry();
  const command = registry.get(name);

  if (!command) {
    return c.json(
      {
        success: false,
        error: `Command not found: ${name}`,
      },
      404
    );
  }

  // Return sanitized command info (exclude template for security)
  return c.json({
    success: true,
    data: {
      name: command.name,
      description: command.description,
      agent: command.agent,
      model: command.model,
      subtask: command.subtask,
      source: command.source,
      hasTemplate: !!command.template,
    },
  });
});

// ============================================================================
// CRUD 操作
// ============================================================================

/**
 * POST /commands - 创建命令
 */
commandsRouter.post('/', async (c) => {
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json();
    const input = CreateCommandInputSchema.parse(body);

    const config = getConfig();
    const manager = module.createCommandManager(config.workdir);
    const result = await manager.create(input);

    if (result.success) {
      return c.json({
        success: true,
        data: {
          name: input.name,
          path: result.path,
        },
      });
    } else {
      return c.json(
        {
          success: false,
          error: result.error,
        },
        400
      );
    }
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Invalid input',
      },
      400
    );
  }
});

/**
 * PUT /commands/:name - 更新命令
 */
commandsRouter.put('/:name{.+}', async (c) => {
  const name = c.req.param('name');
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json();
    const input = UpdateCommandInputSchema.parse(body);

    const config = getConfig();
    const manager = module.createCommandManager(config.workdir);
    const result = await manager.update(name, input);

    if (result.success) {
      return c.json({
        success: true,
        data: {
          name,
          path: result.path,
        },
      });
    } else {
      return c.json(
        {
          success: false,
          error: result.error,
        },
        400
      );
    }
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Invalid input',
      },
      400
    );
  }
});

/**
 * DELETE /commands/:name - 删除命令
 */
commandsRouter.delete('/:name{.+}', async (c) => {
  const name = c.req.param('name');
  const module = await initCommandModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Command module not available',
      },
      503
    );
  }

  const config = getConfig();
  const manager = module.createCommandManager(config.workdir);
  const result = await manager.delete(name);

  if (result.success) {
    return c.json({
      success: true,
      data: {
        name,
        path: result.path,
      },
    });
  } else {
    return c.json(
      {
        success: false,
        error: result.error,
      },
      400
    );
  }
});
