import { performance } from 'node:perf_hooks';
import { c as consola, P as ProjectAnalyzer, g as getTemplatesClient } from '../shared/ccjk.CoCHVXl3.mjs';
import { i as inquirer } from './index6.mjs';
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
import process__default from 'node:process';
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
import { j as join, d as dirname } from '../shared/ccjk.bQ7Dh1g4.mjs';
import { i18n } from './index2.mjs';
import './index10.mjs';
import 'tinyglobby';
import '../shared/ccjk.BBtCGd_g.mjs';
import './constants.mjs';
import 'node:os';
import 'node:url';
import 'node:readline';
import '../shared/ccjk.BAGoDD49.mjs';
import 'stream';
import 'node:tty';
import 'node:async_hooks';
import '../shared/ccjk.Cjgrln_h.mjs';
import 'tty';
import 'fs';
import 'child_process';
import 'node:path';
import 'node:crypto';
import 'buffer';
import 'string_decoder';

var HookType = /* @__PURE__ */ ((HookType2) => {
  HookType2["PreRequest"] = "PreRequest";
  HookType2["PostResponse"] = "PostResponse";
  HookType2["ProviderSwitch"] = "ProviderSwitch";
  HookType2["Error"] = "Error";
  HookType2["SessionStart"] = "SessionStart";
  HookType2["SessionEnd"] = "SessionEnd";
  return HookType2;
})(HookType || {});

const execAsync = promisify(exec);
const DEFAULT_TIMEOUT = 5e3;
const MAX_TIMEOUT = 6e4;
class HookExecutor {
  /**
   * Execute a single hook with the given context
   * @param hook - Hook configuration to execute
   * @param context - Context data to pass to the hook
   * @returns Promise resolving to execution result
   */
  async execute(hook, context) {
    const startTime = Date.now();
    if (hook.enabled === false) {
      return {
        success: true,
        hook,
        executionTime: 0,
        stdout: "",
        stderr: "Hook is disabled"
      };
    }
    const timeout = this.validateTimeout(hook.timeout);
    try {
      const contextJson = JSON.stringify(context, null, 2);
      const result = await this.executeCommand(hook.command, contextJson, timeout);
      const executionTime = Date.now() - startTime;
      return {
        success: result.exitCode === 0,
        hook,
        executionTime,
        stdout: result.stdout,
        stderr: result.stderr,
        exitCode: result.exitCode
      };
    } catch (error) {
      const executionTime = Date.now() - startTime;
      return {
        success: false,
        hook,
        executionTime,
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }
  /**
   * Execute a command with timeout
   * @param command - Command to execute
   * @param contextJson - Context data as JSON string
   * @param timeout - Timeout in milliseconds
   * @returns Promise resolving to command output
   */
  async executeCommand(command, contextJson, timeout) {
    try {
      const env = {
        ...process__default.env,
        CCJK_HOOK_CONTEXT: contextJson
      };
      const { stdout, stderr } = await execAsync(command, {
        timeout,
        env,
        maxBuffer: 1024 * 1024
        // 1MB buffer
      });
      return {
        stdout: stdout.trim(),
        stderr: stderr.trim(),
        exitCode: 0
      };
    } catch (error) {
      return {
        stdout: error.stdout?.trim() || "",
        stderr: error.stderr?.trim() || error.message || "Unknown error",
        exitCode: error.code || 1
      };
    }
  }
  /**
   * Execute a hook asynchronously without waiting for completion
   * Used for hooks that should run in the background
   * @param hook - Hook configuration to execute
   * @param context - Context data to pass to the hook
   */
  executeAsync(hook, context) {
    this.execute(hook, context).catch((error) => {
      console.error("[HookExecutor] Async hook execution failed:", error);
    });
  }
  /**
   * Validate and normalize timeout value
   * @param timeout - Timeout value to validate
   * @returns Validated timeout value
   */
  validateTimeout(timeout) {
    if (!timeout) {
      return DEFAULT_TIMEOUT;
    }
    if (timeout < 0) {
      return DEFAULT_TIMEOUT;
    }
    if (timeout > MAX_TIMEOUT) {
      return MAX_TIMEOUT;
    }
    return timeout;
  }
}
const hookExecutor = new HookExecutor();

const DEFAULT_CONFIG_PATH = join(process__default.env.HOME || process__default.env.USERPROFILE || "~", ".ccjk", "hooks-config.json");
class HookManager {
  hooks = {};
  configPath;
  enabled;
  defaultTimeout;
  /**
   * Create a new HookManager instance
   * @param options - Configuration options
   */
  constructor(options = {}) {
    this.configPath = options.configPath || DEFAULT_CONFIG_PATH;
    this.enabled = options.enabled !== false;
    this.defaultTimeout = options.defaultTimeout || 5e3;
    this.loadHooksFromConfig();
  }
  /**
   * Register a new hook
   * @param hook - Hook configuration to register
   * @returns True if registration was successful
   */
  registerHook(hook) {
    try {
      if (!this.hooks[hook.type]) {
        this.hooks[hook.type] = [];
      }
      const existingIndex = this.hooks[hook.type].findIndex((h) => h.command === hook.command);
      if (existingIndex >= 0) {
        this.hooks[hook.type][existingIndex] = hook;
      } else {
        this.hooks[hook.type].push(hook);
      }
      this.saveHooksToConfig();
      return true;
    } catch (error) {
      console.error("[HookManager] Failed to register hook:", error);
      return false;
    }
  }
  /**
   * Unregister a hook
   * @param type - Hook type
   * @param command - Command to unregister
   * @returns True if unregistration was successful
   */
  unregisterHook(type, command) {
    try {
      if (!this.hooks[type]) {
        return false;
      }
      const initialLength = this.hooks[type].length;
      this.hooks[type] = this.hooks[type].filter((h) => h.command !== command);
      if (this.hooks[type].length === initialLength) {
        return false;
      }
      this.saveHooksToConfig();
      return true;
    } catch (error) {
      console.error("[HookManager] Failed to unregister hook:", error);
      return false;
    }
  }
  /**
   * Execute all hooks of a specific type
   * @param type - Hook type to execute
   * @param context - Context data to pass to hooks
   * @returns Promise resolving to array of execution results
   */
  async executeHooks(type, context) {
    if (!this.enabled) {
      return [];
    }
    const hooksToExecute = this.hooks[type] || [];
    if (hooksToExecute.length === 0) {
      return [];
    }
    const results = [];
    for (const hook of hooksToExecute) {
      const hookWithDefaults = {
        ...hook,
        timeout: hook.timeout || this.defaultTimeout
      };
      if (hook.async) {
        hookExecutor.executeAsync(hookWithDefaults, context);
        results.push({
          success: true,
          hook: hookWithDefaults,
          executionTime: 0,
          stdout: "Executed asynchronously"
        });
      } else {
        const result = await hookExecutor.execute(hookWithDefaults, context);
        results.push(result);
      }
    }
    return results;
  }
  /**
   * Get all registered hooks
   * @returns All hooks organized by type
   */
  getAllHooks() {
    return { ...this.hooks };
  }
  /**
   * Get hooks of a specific type
   * @param type - Hook type
   * @returns Array of hooks for the specified type
   */
  getHooksByType(type) {
    return [...this.hooks[type] || []];
  }
  /**
   * Clear all hooks of a specific type
   * @param type - Hook type to clear
   * @returns True if clearing was successful
   */
  clearHooksByType(type) {
    try {
      this.hooks[type] = [];
      this.saveHooksToConfig();
      return true;
    } catch (error) {
      console.error("[HookManager] Failed to clear hooks:", error);
      return false;
    }
  }
  /**
   * Clear all hooks
   * @returns True if clearing was successful
   */
  clearAllHooks() {
    try {
      this.hooks = {};
      this.saveHooksToConfig();
      return true;
    } catch (error) {
      console.error("[HookManager] Failed to clear all hooks:", error);
      return false;
    }
  }
  /**
   * Enable or disable hooks globally
   * @param enabled - Whether to enable hooks
   */
  setEnabled(enabled) {
    this.enabled = enabled;
  }
  /**
   * Check if hooks are enabled
   * @returns True if hooks are enabled
   */
  isEnabled() {
    return this.enabled;
  }
  /**
   * Load hooks from configuration file
   */
  loadHooksFromConfig() {
    try {
      if (!existsSync(this.configPath)) {
        this.hooks = {};
        return;
      }
      const configContent = readFileSync(this.configPath, "utf-8");
      const config = JSON.parse(configContent);
      this.hooks = this.validateHooksConfig(config);
    } catch (error) {
      console.error("[HookManager] Failed to load hooks from config:", error);
      this.hooks = {};
    }
  }
  /**
   * Save hooks to configuration file
   */
  saveHooksToConfig() {
    try {
      const configDir = dirname(this.configPath);
      if (!existsSync(configDir)) {
        mkdirSync(configDir, { recursive: true });
      }
      const configContent = JSON.stringify(this.hooks, null, 2);
      writeFileSync(this.configPath, configContent, "utf-8");
    } catch (error) {
      console.error("[HookManager] Failed to save hooks to config:", error);
      throw error;
    }
  }
  /**
   * Validate hooks configuration
   * @param config - Configuration to validate
   * @returns Validated configuration
   */
  validateHooksConfig(config) {
    const validatedConfig = {};
    for (const type of Object.values(HookType)) {
      if (config[type] && Array.isArray(config[type])) {
        validatedConfig[type] = config[type].filter((hook) => {
          return hook && typeof hook === "object" && typeof hook.command === "string" && hook.command.length > 0;
        });
      }
    }
    return validatedConfig;
  }
  /**
   * Get configuration file path
   * @returns Path to hooks configuration file
   */
  getConfigPath() {
    return this.configPath;
  }
}
const hookManager = new HookManager();

async function loadHookTemplates() {
  const templates = [];
  const templateDir = join(process.cwd(), "templates", "hooks");
  if (!existsSync(templateDir)) {
    return getDefaultTemplates();
  }
  try {
    const hookTypes = ["pre-commit", "post-test", "lifecycle"];
    for (const type of hookTypes) {
      const typeDir = join(templateDir, type);
      if (!existsSync(typeDir))
        continue;
      const files = require("node:fs").readdirSync(typeDir);
      for (const file of files) {
        if (!file.endsWith(".json"))
          continue;
        try {
          const templatePath = join(typeDir, file);
          const content = readFileSync(templatePath, "utf-8");
          const template = JSON.parse(content);
          templates.push(template);
        } catch (error) {
          console.error(`Failed to load template ${file}:`, error);
        }
      }
    }
  } catch (error) {
    console.error("Failed to load hook templates:", error);
  }
  return templates.length > 0 ? templates : getDefaultTemplates();
}
function getDefaultTemplates() {
  return [
    // Pre-commit hooks
    {
      name: "pre-commit-eslint",
      description: "Run ESLint on staged files",
      type: "pre-commit",
      category: "pre-commit",
      projectTypes: ["typescript", "javascript"],
      trigger: {
        matcher: "git:pre-commit",
        condition: 'git diff --cached --name-only | grep -E "\\.(ts|js|tsx|jsx)$"'
      },
      action: {
        command: "eslint",
        args: ["--fix", "--staged"],
        timeout: 3e4
      },
      enabled: true,
      priority: 100
    },
    {
      name: "pre-commit-prettier",
      description: "Format code with Prettier",
      type: "pre-commit",
      category: "pre-commit",
      projectTypes: ["typescript", "javascript"],
      trigger: {
        matcher: "git:pre-commit",
        condition: 'git diff --cached --name-only | grep -E "\\.(ts|js|tsx|jsx|json|md)$"'
      },
      action: {
        command: "prettier",
        args: ["--write", "--staged"],
        timeout: 15e3
      },
      enabled: true,
      priority: 90
    },
    {
      name: "pre-commit-types",
      description: "Run TypeScript type checking",
      type: "pre-commit",
      category: "pre-commit",
      projectTypes: ["typescript"],
      trigger: {
        matcher: "git:pre-commit"
      },
      action: {
        command: "tsc",
        args: ["--noEmit"],
        timeout: 6e4
      },
      enabled: true,
      priority: 80
    },
    {
      name: "pre-commit-tests",
      description: "Run relevant unit tests",
      type: "pre-commit",
      category: "pre-commit",
      projectTypes: ["typescript", "javascript", "python", "rust"],
      trigger: {
        matcher: "git:pre-commit",
        condition: 'git diff --cached --name-only | grep -E "(test|spec)"'
      },
      action: {
        command: "npm",
        args: ["test", "--", "--related"],
        timeout: 12e4
      },
      enabled: false,
      priority: 70
    },
    // Post-test hooks
    {
      name: "post-test-coverage",
      description: "Generate coverage report after tests",
      type: "post-test",
      category: "post-test",
      projectTypes: ["typescript", "javascript"],
      trigger: {
        matcher: "command:npm test"
      },
      action: {
        command: "npm",
        args: ["run", "coverage:report"],
        timeout: 3e4
      },
      enabled: true,
      priority: 100
    },
    {
      name: "post-test-summary",
      description: "Summarize test results",
      type: "post-test",
      category: "post-test",
      projectTypes: ["typescript", "javascript", "python", "rust", "go"],
      trigger: {
        matcher: "command:*test*"
      },
      action: {
        command: "ccjk",
        args: ["test:summary"],
        timeout: 1e4
      },
      enabled: true,
      priority: 90
    },
    {
      name: "post-test-notify",
      description: "Send test result notifications",
      type: "post-test",
      category: "post-test",
      projectTypes: ["typescript", "javascript", "python"],
      trigger: {
        matcher: "command:*test*",
        condition: "exitCode != 0"
      },
      action: {
        command: "ccjk",
        args: ["notify", "--type", "test-failed"],
        timeout: 5e3
      },
      enabled: false,
      priority: 80
    },
    {
      name: "post-test-benchmark",
      description: "Track test performance metrics",
      type: "post-test",
      category: "post-test",
      projectTypes: ["typescript", "javascript", "python", "rust"],
      trigger: {
        matcher: "command:*test*"
      },
      action: {
        command: "ccjk",
        args: ["benchmark:track", "--category", "test"],
        timeout: 15e3
      },
      enabled: true,
      priority: 70
    },
    // Lifecycle hooks
    {
      name: "post-install-setup",
      description: "Run setup after dependencies install",
      type: "post-install",
      category: "lifecycle",
      projectTypes: ["typescript", "javascript"],
      trigger: {
        matcher: "command:npm install"
      },
      action: {
        command: "npm",
        args: ["run", "postinstall"],
        timeout: 6e4
      },
      enabled: true,
      priority: 100
    },
    {
      name: "pre-build-clean",
      description: "Clean build directory before build",
      type: "pre-build",
      category: "lifecycle",
      projectTypes: ["typescript", "javascript", "rust", "go"],
      trigger: {
        matcher: "command:*build*"
      },
      action: {
        command: "rm",
        args: ["-rf", "dist", "build"],
        timeout: 5e3
      },
      enabled: true,
      priority: 100
    },
    {
      name: "post-build-size",
      description: "Analyze build size after build",
      type: "post-build",
      category: "lifecycle",
      projectTypes: ["typescript", "javascript"],
      trigger: {
        matcher: "command:*build*"
      },
      action: {
        command: "ccjk",
        args: ["build:analyze"],
        timeout: 15e3
      },
      enabled: true,
      priority: 90
    },
    {
      name: "pre-push-checks",
      description: "Run all checks before pushing",
      type: "pre-push",
      category: "lifecycle",
      projectTypes: ["typescript", "javascript", "python", "rust"],
      trigger: {
        matcher: "git:pre-push"
      },
      action: {
        command: "npm",
        args: ["run", "ci"],
        timeout: 3e5
      },
      enabled: true,
      priority: 100
    }
  ];
}

async function validateHookTrigger(trigger, projectInfo) {
  try {
    const { matcher, condition } = trigger;
    if (!matcher || !matcher.includes(":")) {
      throw new Error(`Invalid trigger matcher format: ${matcher}`);
    }
    const [type, pattern] = matcher.split(":", 2);
    switch (type) {
      case "git":
        return await validateGitTrigger(pattern, condition, projectInfo);
      case "file":
        return await validateFileTrigger(pattern, condition, projectInfo);
      case "command":
        return await validateCommandTrigger(pattern, condition, projectInfo);
      case "schedule":
        return await validateScheduleTrigger(pattern, condition);
      case "webhook":
        return await validateWebhookTrigger(pattern, condition);
      default:
        throw new Error(`Unknown trigger type: ${type}`);
    }
  } catch (error) {
    console.error(`Trigger validation failed: ${error}`);
    return false;
  }
}
async function validateGitTrigger(pattern, condition, _projectInfo) {
  const gitDir = join(process.cwd(), ".git");
  if (!existsSync(gitDir)) {
    throw new Error("Git repository not found");
  }
  const validGitHooks = [
    "pre-commit",
    "post-commit",
    "commit-msg",
    "prepare-commit-msg",
    "pre-push",
    "post-push",
    "pre-merge",
    "post-merge",
    "pre-rebase",
    "post-rebase",
    "pre-checkout",
    "post-checkout",
    "pre-receive",
    "post-receive",
    "update",
    "pre-applypatch",
    "post-applypatch",
    "applypatch-msg"
  ];
  if (!validGitHooks.includes(pattern)) {
    throw new Error(`Invalid git hook: ${pattern}`);
  }
  if (condition) {
    const validConditions = [
      "staged",
      "unstaged",
      "branch=",
      "files=",
      "message=",
      "merge"
    ];
    const hasValidCondition = validConditions.some((c) => condition.includes(c));
    const isFilePatternCondition = /^[\w\-.*]+(\s*\|\|\s*[\w\-.*]+)*$/.test(condition.trim());
    if (!hasValidCondition && !isFilePatternCondition) {
      throw new Error(`Invalid git condition: ${condition}`);
    }
  }
  return true;
}
async function validateFileTrigger(pattern, condition, _projectInfo) {
  if (!pattern || pattern.length === 0) {
    throw new Error("File pattern cannot be empty");
  }
  const dangerousPatterns = [
    "**/.git/**",
    "**/node_modules/**",
    "**/.ccjk/**",
    "**/dist/**",
    "**/build/**",
    "**/*.{exe,dll,so,dylib}"
  ];
  const isDangerous = dangerousPatterns.some((p) => pattern.includes(p));
  if (isDangerous) {
    console.warn(`Warning: Potentially dangerous file pattern: ${pattern}`);
  }
  if (condition) {
    const validFileConditions = [
      "created",
      "modified",
      "deleted",
      "size>",
      "size<",
      "count>",
      "count<"
    ];
    const hasValidCondition = validFileConditions.some((c) => condition.includes(c));
    if (!hasValidCondition) {
      throw new Error(`Invalid file condition: ${condition}`);
    }
  }
  return true;
}
async function validateCommandTrigger(pattern, condition, _projectInfo) {
  if (!pattern || pattern.length === 0) {
    throw new Error("Command pattern cannot be empty");
  }
  const validPatterns = [
    "npm",
    "yarn",
    "pnpm",
    "pip",
    "cargo",
    "go",
    "mvn",
    "gradle",
    "make",
    "tsc",
    "node",
    "python",
    "pytest",
    "jest",
    "vitest",
    "mocha"
  ];
  const isValidPattern = validPatterns.some((p) => pattern.includes(p));
  if (!isValidPattern) {
    console.warn(`Warning: Unusual command pattern: ${pattern}`);
  }
  if (condition) {
    const validCommandConditions = [
      "exitCode=",
      "exitCode!=",
      "duration>",
      "duration<",
      "stdout=",
      "stderr=",
      "output="
    ];
    const hasValidCondition = validCommandConditions.some((c) => condition.includes(c));
    if (!hasValidCondition) {
      throw new Error(`Invalid command condition: ${condition}`);
    }
  }
  return true;
}
async function validateScheduleTrigger(pattern, _condition) {
  const cronParts = pattern.split(" ");
  if (cronParts.length !== 5) {
    throw new Error(`Invalid cron pattern: ${pattern}. Expected 5 parts.`);
  }
  const validateCronPart = (part, min, max) => {
    if (part === "*")
      return true;
    if (part.includes("/")) {
      const [, step] = part.split("/");
      const stepNum = Number.parseInt(step);
      return !isNaN(stepNum) && stepNum > 0;
    }
    if (part.includes("-")) {
      const [start, end] = part.split("-");
      const startNum = Number.parseInt(start);
      const endNum = Number.parseInt(end);
      return !isNaN(startNum) && !isNaN(endNum) && startNum <= endNum;
    }
    if (part.includes(",")) {
      return part.split(",").every((p) => validateCronPart(p, min, max));
    }
    const num = Number.parseInt(part);
    return !isNaN(num) && num >= min && num <= max;
  };
  const validations = [
    validateCronPart(cronParts[0], 0, 59),
    // minutes
    validateCronPart(cronParts[1], 0, 23),
    // hours
    validateCronPart(cronParts[2], 1, 31),
    // days
    validateCronPart(cronParts[3], 1, 12),
    // months
    validateCronPart(cronParts[4], 0, 7)
    // weekdays
  ];
  if (!validations.every((v) => v)) {
    throw new Error(`Invalid cron pattern: ${pattern}`);
  }
  return true;
}
async function validateWebhookTrigger(pattern, condition) {
  try {
    const url = new URL(pattern);
    if (!["http:", "https:"].includes(url.protocol)) {
      throw new Error(`Invalid webhook protocol: ${url.protocol}`);
    }
  } catch {
    throw new Error(`Invalid webhook URL: ${pattern}`);
  }
  if (condition) {
    const validWebhookConditions = [
      "method=",
      "header=",
      "body=",
      "status=",
      "content-type="
    ];
    const hasValidCondition = validWebhookConditions.some((c) => condition.includes(c));
    if (!hasValidCondition) {
      throw new Error(`Invalid webhook condition: ${condition}`);
    }
  }
  return true;
}

async function ccjkHooks(options = {}) {
  const startTime = performance.now();
  const { json = false, dryRun = false } = options;
  if (!json) {
    consola.log(i18n.t("hooks.analyzingProject"));
  }
  try {
    const analyzer = new ProjectAnalyzer();
    const projectInfo = await analyzer.analyze(process.cwd());
    const projectType = projectInfo.projectType;
    const framework = projectInfo.frameworks?.[0]?.name || "none";
    if (!json) {
      consola.success(i18n.t("hooks.projectDetected", {
        type: projectType,
        framework
      }));
    }
    const isZh = i18n.language === "zh-CN";
    const allHookTemplates = await loadHookTemplates();
    let recommendedHooks = allHookTemplates.filter(
      (template) => template.projectTypes.includes(projectType)
    );
    try {
      const templatesClient = getTemplatesClient({ language: isZh ? "zh-CN" : "en" });
      const cloudHooks = await Promise.race([
        templatesClient.getHooks(),
        new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 3e3))
      ]);
      if (cloudHooks.length > 0) {
        consola.success(isZh ? `\u4ECE\u4E91\u7AEF\u83B7\u53D6 ${cloudHooks.length} \u4E2A\u94A9\u5B50` : `Fetched ${cloudHooks.length} hooks from cloud`);
        const languages = projectInfo.languages?.map((l) => l.language.toLowerCase()) || [];
        const frameworks = projectInfo.frameworks?.map((f) => f.name.toLowerCase()) || [];
        const relevantHooks = cloudHooks.filter((hook) => {
          const tags = hook.tags || [];
          const category = hook.category || "";
          const compatibility = hook.compatibility || {};
          return tags.some((tag) => languages.includes(tag) || frameworks.includes(tag) || projectType.includes(tag)) || (compatibility.languages || []).some((lang) => languages.includes(lang.toLowerCase())) || (compatibility.frameworks || []).some((fw) => frameworks.includes(fw.toLowerCase())) || category === "pre-commit" || category === "commit-msg";
        });
        const localHookNames = new Set(recommendedHooks.map((h) => h.name.toLowerCase()));
        for (const hook of relevantHooks.length > 0 ? relevantHooks : cloudHooks.slice(0, 10)) {
          const hookName = (hook.name_zh_cn && isZh ? hook.name_zh_cn : hook.name_en).toLowerCase();
          if (localHookNames.has(hookName)) {
            continue;
          }
          const hookConfig = {
            name: hook.name_zh_cn && isZh ? hook.name_zh_cn : hook.name_en,
            description: hook.description_zh_cn && isZh ? hook.description_zh_cn : hook.description_en || "",
            type: hook.category || "pre-commit",
            category: hook.category || "pre-commit",
            projectTypes: ["all"],
            trigger: {
              matcher: `git:${hook.category || "pre-commit"}`,
              condition: void 0
            },
            action: {
              command: hook.install_command || "echo",
              args: [hook.name_en],
              timeout: 3e4
            },
            enabled: true,
            priority: hook.rating_average ? Math.round(hook.rating_average * 20) : 50
          };
          recommendedHooks.push(hookConfig);
        }
      }
    } catch {
    }
    const filteredHooks = filterHooks(recommendedHooks, options);
    if (filteredHooks.length === 0) {
      if (json) {
        return { success: true, hooks: [], message: "No hooks found matching criteria" };
      }
      consola.warn(i18n.t("hooks.noHooksFound"));
      return;
    }
    const hooksByCategory = groupHooksByCategory(filteredHooks);
    if (!json) {
      displayHooks(hooksByCategory, options);
    }
    if (!dryRun && !json) {
      const { shouldInstall } = await inquirer.prompt([{
        type: "confirm",
        name: "shouldInstall",
        message: i18n.t("hooks.installPrompt", { count: filteredHooks.length }),
        default: true
      }]);
      if (!shouldInstall) {
        consola.info(i18n.t("hooks.installCancelled"));
        return;
      }
    }
    if (!json) {
      consola.log(i18n.t("hooks.installingHooks"));
    }
    const installedHooks = [];
    const errors = [];
    for (const hook of filteredHooks) {
      try {
        if (dryRun) {
          if (json) {
            installedHooks.push(hook.name);
          } else {
            consola.log(`  ${i18n.t("hooks.wouldInstall", { name: hook.name })}`);
          }
          continue;
        }
        const isValid = await validateHookTrigger(hook.trigger, projectInfo);
        if (!isValid) {
          throw new Error(i18n.t("hooks.invalidTrigger", { trigger: hook.trigger.matcher }));
        }
        const hookForManager = {
          command: hook.action.command,
          args: hook.action.args || [],
          type: hook.type,
          // Type assertion to handle the mismatch
          async: false,
          timeout: hook.action.timeout || 5e3,
          workingDir: hook.action.workingDirectory,
          env: hook.action.environment,
          description: hook.description
        };
        hookManager.registerHook(hookForManager);
        installedHooks.push(hook.name);
        if (!json) {
          consola.success(`  ${i18n.t("hooks.installed", { name: hook.name })}`);
        }
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        errors.push({ hook: hook.name, error: errorMessage });
        if (!json) {
          consola.error(`  ${i18n.t("hooks.installFailed", { name: hook.name })}: ${errorMessage}`);
        }
      }
    }
    const duration = Math.round(performance.now() - startTime);
    if (json) {
      return {
        success: errors.length === 0,
        installed: installedHooks,
        errors,
        duration,
        hooks: installedHooks.map((name) => ({ name, status: "installed" }))
      };
    }
    if (installedHooks.length > 0) {
      consola.success(
        i18n.t("hooks.installSuccess", {
          count: installedHooks.length,
          duration
        })
      );
    }
    if (errors.length > 0) {
      consola.warn(
        i18n.t("hooks.installPartial", {
          failed: errors.length,
          total: filteredHooks.length
        })
      );
    }
    if (installedHooks.length > 0 && !dryRun) {
      displayTestingInstructions(hooksByCategory);
    }
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    if (json) {
      return {
        success: false,
        error: errorMessage,
        hooks: []
      };
    }
    consola.error(i18n.t("hooks.installError", { error: errorMessage }));
    throw error;
  }
}
function filterHooks(hooks, options) {
  let filtered = hooks;
  if (options.type && options.type !== "all") {
    filtered = filtered.filter((hook) => hook.type === options.type);
  }
  if (options.category && options.category !== "all") {
    filtered = filtered.filter((hook) => hook.category === options.category);
  }
  if (options.exclude && options.exclude.length > 0) {
    filtered = filtered.filter(
      (hook) => !options.exclude.includes(hook.name)
    );
  }
  if (options.enabled !== void 0) {
    filtered = filtered.filter((hook) => hook.enabled === options.enabled);
  }
  if (options.priority !== void 0) {
    filtered = filtered.sort((a, b) => {
      const priorityA = a.priority || 0;
      const priorityB = b.priority || 0;
      return priorityB - priorityA;
    });
  }
  return filtered;
}
function groupHooksByCategory(hooks) {
  const groups = {
    "pre-commit": [],
    "post-test": [],
    "lifecycle": []
  };
  for (const hook of hooks) {
    const category = hook.category || "lifecycle";
    if (!groups[category]) {
      groups[category] = [];
    }
    groups[category].push(hook);
  }
  return groups;
}
function displayHooks(hooksByCategory, options) {
  const totalHooks = Object.values(hooksByCategory).flat().length;
  consola.log(i18n.t("hooks.foundHooks", { count: totalHooks }));
  consola.log("");
  for (const [category, hooks] of Object.entries(hooksByCategory)) {
    if (hooks.length === 0)
      continue;
    consola.log(`${i18n.t(`hooks.category.${category}`)}:`);
    for (const hook of hooks) {
      const status = hook.enabled ? "\u2705" : "\u23F8\uFE0F";
      consola.log(`  ${status} ${hook.name.padEnd(25)} - ${hook.description}`);
      if (options.verbose) {
        consola.log(`     ${i18n.t("hooks.trigger")}: ${hook.trigger.matcher}`);
        consola.log(`     ${i18n.t("hooks.command")}: ${hook.action.command}`);
      }
    }
    consola.log("");
  }
}
function displayTestingInstructions(hooksByCategory) {
  consola.log("");
  consola.info(i18n.t("hooks.testingInstructions"));
  consola.log("");
  if (hooksByCategory["pre-commit"].length > 0) {
    consola.log(`  \u2022 ${i18n.t("hooks.testPreCommit")}`);
  }
  if (hooksByCategory["post-test"].length > 0) {
    consola.log(`  \u2022 ${i18n.t("hooks.testPostTest")}`);
  }
  if (hooksByCategory.lifecycle.length > 0) {
    consola.log(`  \u2022 ${i18n.t("hooks.testLifecycle")}`);
  }
  consola.log(`  \u2022 ${i18n.t("hooks.listHooks")}: ccjk hooks list`);
  consola.log(`  \u2022 ${i18n.t("hooks.testHooks")}: ccjk hooks test`);
}

export { ccjkHooks };
