/**
 * Command 管理器
 *
 * 负责命令的 CRUD 操作（创建、更新、删除）
 * 命令存储在文件系统的 Markdown 文件中
 */

import * as fs from 'fs/promises';
import * as path from 'path';
import * as yaml from 'yaml';
import type { Command, CommandFrontmatter } from './types.js';
import { commandLoader } from './loader.js';
import { getCommandRegistry } from './registry.js';

/**
 * 创建命令的输入参数
 */
export interface CreateCommandInput {
  /** 命令名称（支持嵌套如 deploy/staging） */
  name: string;
  /** 命令描述 */
  description?: string;
  /** 提示词模板 */
  template: string;
  /** 指定 Agent */
  agent?: string;
  /** 指定模型 */
  model?: string;
  /** 是否作为子任务执行 */
  subtask?: boolean;
  /** 存储位置 */
  scope: 'user' | 'project';
}

/**
 * 更新命令的输入参数
 */
export interface UpdateCommandInput {
  /** 命令描述 */
  description?: string;
  /** 提示词模板 */
  template?: string;
  /** 指定 Agent */
  agent?: string;
  /** 指定模型 */
  model?: string;
  /** 是否作为子任务执行 */
  subtask?: boolean;
}

/**
 * 命令完整内容（包含 template）
 */
export interface CommandContent {
  name: string;
  description?: string;
  template: string;
  agent?: string;
  model?: string;
  subtask?: boolean;
  source: string;
  sourcePath?: string;
}

/**
 * 操作结果
 */
export interface CommandOperationResult {
  success: boolean;
  path?: string;
  error?: string;
}

/**
 * 命令管理器
 */
export class CommandManager {
  private workdir: string;

  constructor(workdir: string = process.cwd()) {
    this.workdir = workdir;
  }

  /**
   * 验证命令名称是否合法
   * 防止路径遍历攻击
   */
  private validateCommandName(name: string): boolean {
    // 不能为空
    if (!name || name.trim() === '') {
      return false;
    }

    // 不能包含 .. 或绝对路径
    if (name.includes('..') || path.isAbsolute(name)) {
      return false;
    }

    // 只允许字母、数字、连字符、下划线和斜杠
    if (!/^[a-zA-Z0-9_\-/]+$/.test(name)) {
      return false;
    }

    // 不能以斜杠开头或结尾
    if (name.startsWith('/') || name.endsWith('/')) {
      return false;
    }

    // 不能有连续的斜杠
    if (name.includes('//')) {
      return false;
    }

    return true;
  }

  /**
   * 生成 Markdown 内容
   */
  private generateMarkdownContent(input: {
    description?: string;
    template: string;
    agent?: string;
    model?: string;
    subtask?: boolean;
  }): string {
    const frontmatter: CommandFrontmatter = {};

    if (input.description) {
      frontmatter.description = input.description;
    }
    if (input.agent) {
      frontmatter.agent = input.agent;
    }
    if (input.model) {
      frontmatter.model = input.model;
    }
    if (input.subtask !== undefined) {
      frontmatter.subtask = input.subtask;
    }

    // 如果有 frontmatter，生成 YAML
    if (Object.keys(frontmatter).length > 0) {
      const yamlStr = yaml.stringify(frontmatter).trim();
      return `---\n${yamlStr}\n---\n\n${input.template}`;
    }

    // 没有 frontmatter，直接返回模板
    return input.template;
  }

  /**
   * 获取命令文件路径
   */
  getCommandFilePath(name: string, scope: 'user' | 'project'): string {
    const baseDir =
      scope === 'user'
        ? commandLoader.getUserCommandsDir()
        : commandLoader.getProjectCommandsDir(this.workdir);

    return path.join(baseDir, `${name}.md`);
  }

  /**
   * 创建命令
   */
  async create(input: CreateCommandInput): Promise<CommandOperationResult> {
    // 验证命令名称
    if (!this.validateCommandName(input.name)) {
      return {
        success: false,
        error: `Invalid command name: ${input.name}. Name can only contain letters, numbers, hyphens, underscores, and forward slashes.`,
      };
    }

    // 验证模板不为空
    if (!input.template || input.template.trim() === '') {
      return {
        success: false,
        error: 'Template cannot be empty',
      };
    }

    // 检查是否已存在同名命令
    const registry = getCommandRegistry();
    const existing = registry.get(input.name);
    if (existing) {
      return {
        success: false,
        error: `Command already exists: ${input.name} (source: ${existing.source})`,
      };
    }

    // 生成文件路径
    const filePath = this.getCommandFilePath(input.name, input.scope);

    // 确保目录存在
    const dir = path.dirname(filePath);
    try {
      await fs.mkdir(dir, { recursive: true });
    } catch (error) {
      return {
        success: false,
        error: `Failed to create directory: ${dir}`,
      };
    }

    // 生成 Markdown 内容
    const content = this.generateMarkdownContent({
      description: input.description,
      template: input.template,
      agent: input.agent,
      model: input.model,
      subtask: input.subtask,
    });

    // 写入文件
    try {
      await fs.writeFile(filePath, content, 'utf-8');
    } catch (error) {
      return {
        success: false,
        error: `Failed to write file: ${filePath}`,
      };
    }

    // 重新加载命令注册表
    await registry.reload(this.workdir);

    return {
      success: true,
      path: filePath,
    };
  }

  /**
   * 更新命令
   */
  async update(
    name: string,
    input: UpdateCommandInput
  ): Promise<CommandOperationResult> {
    // 验证命令名称
    if (!this.validateCommandName(name)) {
      return {
        success: false,
        error: `Invalid command name: ${name}`,
      };
    }

    // 获取现有命令
    const registry = getCommandRegistry();
    const existing = registry.get(name);

    if (!existing) {
      return {
        success: false,
        error: `Command not found: ${name}`,
      };
    }

    // 内置命令不可修改
    if (existing.source === 'builtin') {
      return {
        success: false,
        error: `Cannot modify builtin command: ${name}`,
      };
    }

    // 获取文件路径
    const filePath = existing.sourcePath;
    if (!filePath) {
      return {
        success: false,
        error: `Command source path not found: ${name}`,
      };
    }

    // 合并更新
    const updatedCommand = {
      description: input.description ?? existing.description,
      template: input.template ?? existing.template,
      agent: input.agent ?? existing.agent,
      model: input.model ?? existing.model,
      subtask: input.subtask ?? existing.subtask,
    };

    // 生成新的 Markdown 内容
    const content = this.generateMarkdownContent(updatedCommand);

    // 写入文件
    try {
      await fs.writeFile(filePath, content, 'utf-8');
    } catch (error) {
      return {
        success: false,
        error: `Failed to write file: ${filePath}`,
      };
    }

    // 重新加载命令注册表
    await registry.reload(this.workdir);

    return {
      success: true,
      path: filePath,
    };
  }

  /**
   * 删除命令
   */
  async delete(name: string): Promise<CommandOperationResult> {
    // 验证命令名称
    if (!this.validateCommandName(name)) {
      return {
        success: false,
        error: `Invalid command name: ${name}`,
      };
    }

    // 获取现有命令
    const registry = getCommandRegistry();
    const existing = registry.get(name);

    if (!existing) {
      return {
        success: false,
        error: `Command not found: ${name}`,
      };
    }

    // 内置命令不可删除
    if (existing.source === 'builtin') {
      return {
        success: false,
        error: `Cannot delete builtin command: ${name}`,
      };
    }

    // 获取文件路径
    const filePath = existing.sourcePath;
    if (!filePath) {
      return {
        success: false,
        error: `Command source path not found: ${name}`,
      };
    }

    // 删除文件
    try {
      await fs.unlink(filePath);
    } catch (error) {
      return {
        success: false,
        error: `Failed to delete file: ${filePath}`,
      };
    }

    // 尝试删除空的父目录
    try {
      const dir = path.dirname(filePath);
      const files = await fs.readdir(dir);
      if (files.length === 0) {
        await fs.rmdir(dir);
      }
    } catch {
      // 忽略目录删除失败
    }

    // 重新加载命令注册表
    await registry.reload(this.workdir);

    return {
      success: true,
      path: filePath,
    };
  }

  /**
   * 获取命令完整内容（包含 template）
   */
  async getContent(name: string): Promise<{
    success: boolean;
    data?: CommandContent;
    error?: string;
  }> {
    // 验证命令名称
    if (!this.validateCommandName(name)) {
      return {
        success: false,
        error: `Invalid command name: ${name}`,
      };
    }

    // 获取命令
    const registry = getCommandRegistry();
    const command = registry.get(name);

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

    return {
      success: true,
      data: {
        name: command.name,
        description: command.description,
        template: command.template,
        agent: command.agent,
        model: command.model,
        subtask: command.subtask,
        source: command.source,
        sourcePath: command.sourcePath,
      },
    };
  }
}

/**
 * 创建命令管理器实例
 */
export function createCommandManager(
  workdir: string = process.cwd()
): CommandManager {
  return new CommandManager(workdir);
}
