import { spawnSync } from 'node:child_process';
import { inspect } from 'node:util';

// src/platform/ai-services/internal/cli-management.ts
function stringifyUnknown(value) {
  if (value === void 0 || value === null) {
    return "";
  }
  if (typeof value === "string") {
    return value;
  }
  if (Buffer.isBuffer(value)) {
    return value.toString("utf8");
  }
  if (value instanceof Error) {
    return value.stack || value.message;
  }
  return inspect(value, { depth: 6, breakLength: 120 });
}
function getErrorSummary(error) {
  if (error instanceof Error) {
    return `${error.name}: ${error.message}`;
  }
  return stringifyUnknown(error) || "Unknown error";
}

// src/platform/types/app.ts
var AI_SERVICE = {
  CLAUDE: "claude",
  CODEX: "codex",
  GEMINI: "gemini"
};

// src/platform/ai-services/internal/semver.ts
var SEMVER_PATTERN = /(\d+\.\d+\.\d+)/;
function extractSemver(value) {
  const match = value.match(SEMVER_PATTERN);
  return match?.[1] ?? null;
}
function isVersionOutdated(current, target) {
  const currentParts = current.split(".").map(Number);
  const targetParts = target.split(".").map(Number);
  for (let index = 0; index < Math.max(currentParts.length, targetParts.length); index += 1) {
    const currentPart = currentParts[index] ?? 0;
    const targetPart = targetParts[index] ?? 0;
    if (currentPart < targetPart) {
      return true;
    }
    if (currentPart > targetPart) {
      return false;
    }
  }
  return false;
}

// src/platform/ai-services/internal/cli-management.ts
var SERVICE_BINARY_NAMES = {
  [AI_SERVICE.CODEX]: "codex",
  [AI_SERVICE.GEMINI]: "gemini",
  [AI_SERVICE.CLAUDE]: "claude"
};
var SERVICE_INSTALL_PACKAGES = {
  [AI_SERVICE.CODEX]: "@openai/codex",
  [AI_SERVICE.GEMINI]: "@google/gemini-cli",
  [AI_SERVICE.CLAUDE]: "@anthropic-ai/claude-code"
};
function getBinaryName(service) {
  return SERVICE_BINARY_NAMES[service];
}
function getInstallPackageName(service) {
  return SERVICE_INSTALL_PACKAGES[service];
}
function isCliAvailable(service, trace) {
  const binaryName = getBinaryName(service);
  trace("cli-check:start", `${service} -> ${binaryName} --version`);
  const result = spawnSync(binaryName, ["--version"], {
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 2,
    timeout: 1e4
  });
  if (result.error || result.status !== 0) {
    trace("cli-check:missing", getErrorSummary(result.error || result.stderr || result.status));
    return false;
  }
  trace("cli-check:ok", `${service}`);
  return true;
}
function installCli(service, trace) {
  const packageName = getInstallPackageName(service);
  trace("cli-install:start", `${service} -> ${packageName}`);
  const result = spawnSync("npm", ["install", "-g", packageName], {
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 20,
    stdio: "inherit"
  });
  if (result.error || result.status !== 0) {
    trace("cli-install:failed", getErrorSummary(result.error || result.stderr || result.status));
    throw new Error(`${service} CLI \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. package=${packageName}`);
  }
  trace("cli-install:done", `${service}`);
}
function getInstalledVersion(service, trace) {
  const binaryName = getBinaryName(service);
  trace("cli-version:current:start", binaryName);
  const result = spawnSync(binaryName, ["--version"], {
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 2,
    timeout: 1e4
  });
  if (result.error || result.status !== 0) {
    trace("cli-version:current:failed", getErrorSummary(result.error || result.stderr || result.status));
    return null;
  }
  const output = (result.stdout || "").trim();
  const version = extractSemver(output);
  if (!version) {
    trace("cli-version:current:parse-failed", output);
    return null;
  }
  trace("cli-version:current:ok", version);
  return version;
}
function getLatestVersion(service, trace) {
  const packageName = getInstallPackageName(service);
  trace("cli-version:latest:start", packageName);
  const result = spawnSync("npm", ["view", packageName, "version"], {
    encoding: "utf8",
    maxBuffer: 1024 * 1024,
    timeout: 15e3
  });
  if (result.error || result.status !== 0) {
    trace("cli-version:latest:failed", getErrorSummary(result.error || result.stderr || result.status));
    return null;
  }
  const version = (result.stdout || "").trim();
  const normalizedVersion = extractSemver(version);
  if (!normalizedVersion) {
    trace("cli-version:latest:parse-failed", version);
    return null;
  }
  trace("cli-version:latest:ok", normalizedVersion);
  return normalizedVersion;
}
function upgradeServiceCli(service, trace, minimumVersion) {
  const packageName = getInstallPackageName(service);
  const packageSpec = `${packageName}@latest`;
  trace("cli-upgrade:start", `${service} -> ${packageSpec}`);
  const result = spawnSync("npm", ["install", "-g", packageSpec], {
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 20,
    stdio: "inherit"
  });
  if (result.error || result.status !== 0) {
    trace("cli-upgrade:failed", getErrorSummary(result.error || result.stderr || result.status));
    return false;
  }
  trace("cli-upgrade:done", service);
  return true;
}

// src/platform/ai-services/internal/health-checkers/messages.ts
var createHealthCheckMessage = (service, status, context) => {
  const binary = context?.binaryName ?? service;
  const pkg = context?.packageName ?? service;
  switch (status) {
    case "ready":
      return `[${service}] \uC11C\uBE44\uC2A4\uAC00 \uC815\uC0C1 \uC0C1\uD0DC\uC785\uB2C8\uB2E4.`;
    case "not-installed":
      return [
        `[${service}] CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`,
        "\uC790\uB3D9 \uC124\uCE58\uB97C \uC2DC\uB3C4\uD569\uB2C8\uB2E4..."
      ].join("\n");
    case "install-failed":
      return [
        `[${service}] CLI \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.`,
        "",
        "\uB2E4\uC74C \uBA85\uB839\uC5B4\uB85C \uC218\uB3D9 \uC124\uCE58\uD574 \uC8FC\uC138\uC694:",
        `  $ npm install -g ${pkg}`,
        "",
        "\uC124\uCE58 \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uC8FC\uC138\uC694."
      ].join("\n");
    case "needs-setup":
      return [
        `[${service}] CLI \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`,
        "",
        `${binary} \uB97C \uC9C1\uC811 \uC2E4\uD589\uD558\uC5EC \uCD08\uAE30 \uC124\uC815(\uB85C\uADF8\uC778 \uB4F1)\uC744 \uC644\uB8CC\uD574 \uC8FC\uC138\uC694:`,
        `  $ ${binary}`,
        "",
        "\uCD08\uAE30 \uC124\uC815 \uC644\uB8CC \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uC8FC\uC138\uC694."
      ].join("\n");
    case "unknown-error":
    default:
      return [
        `[${service}] \uC11C\uBE44\uC2A4 \uC0C1\uD0DC\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`,
        "",
        "\uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uACE0 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.",
        `\uBB38\uC81C\uAC00 \uC9C0\uC18D\uB418\uBA74 '${binary} --version' \uBA85\uB839\uC5B4\uB85C CLI \uC0C1\uD0DC\uB97C \uD655\uC778\uD574 \uC8FC\uC138\uC694.`
      ].join("\n");
  }
};
var createStepMessage = (step, service, detail) => {
  const suffix = detail ? ` (${detail})` : "";
  switch (step) {
    case "start":
      return `[${service}] \uC11C\uBE44\uC2A4 \uC0C1\uD0DC\uB97C \uC810\uAC80\uD558\uACE0 \uC788\uC2B5\uB2C8\uB2E4...`;
    case "install-attempt":
      return `  ! ${service} CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC790\uB3D9 \uC124\uCE58\uB97C \uC2DC\uB3C4\uD569\uB2C8\uB2E4...`;
    case "install-ok":
      return `  + CLI \uC124\uCE58 \uD655\uC778${suffix}`;
    case "version-current":
      return `  + \uD604\uC7AC \uBC84\uC804 \uD655\uC778${suffix}`;
    case "version-latest-unavailable":
      return `  ! \uCD5C\uC2E0 \uBC84\uC804 \uD655\uC778\uC5D0 \uC2E4\uD328\uD574 \uD604\uC7AC \uBC84\uC804\uC73C\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4.${suffix}`;
    case "version-ok":
      return `  + \uCD5C\uC2E0 \uBC84\uC804\uC785\uB2C8\uB2E4${suffix}`;
    case "version-updating":
      return `  ~ \uC5C5\uB370\uC774\uD2B8 \uC911...${suffix}`;
    case "version-update-ok":
      return `  + \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC${suffix}`;
    case "version-update-failed":
      return `  ! \uC5C5\uB370\uC774\uD2B8\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uD604\uC7AC \uBC84\uC804\uC73C\uB85C \uACC4\uC18D \uC9C4\uD589\uD569\uB2C8\uB2E4.${suffix}`;
    default:
      return "";
  }
};

// src/platform/ai-services/internal/health-checkers/index.ts
function runServiceHealthCheck(service, trace) {
  const binaryName = getBinaryName(service);
  const packageName = getInstallPackageName(service);
  const messageContext = { binaryName, packageName };
  console.log(createStepMessage("start", service));
  const installResult = checkInstallation(service, binaryName, packageName, trace);
  if (installResult) {
    return installResult;
  }
  const { currentVersion, latestVersion } = checkAndUpdateVersion(service, trace);
  return {
    message: createHealthCheckMessage(service, "ready", messageContext),
    ok: true,
    service,
    status: "ready",
    ...currentVersion ? { currentVersion } : {},
    ...latestVersion ? { latestVersion } : {}
  };
}
function checkInstallation(service, binaryName, packageName, trace) {
  if (isCliAvailable(service, trace)) {
    const version = getInstalledVersion(service, trace);
    console.log(createStepMessage("install-ok", service, version ? `v${version}` : void 0));
    return null;
  }
  console.log(createStepMessage("install-attempt", service));
  try {
    installCli(service, trace);
  } catch {
    return {
      message: createHealthCheckMessage(service, "install-failed", { binaryName, packageName }),
      ok: false,
      service,
      status: "install-failed"
    };
  }
  if (!isCliAvailable(service, trace)) {
    return {
      message: createHealthCheckMessage(service, "install-failed", { binaryName, packageName }),
      ok: false,
      service,
      status: "install-failed"
    };
  }
  return {
    message: createHealthCheckMessage(service, "needs-setup", { binaryName, packageName }),
    ok: false,
    service,
    status: "needs-setup"
  };
}
function checkAndUpdateVersion(service, trace) {
  const currentVersion = getInstalledVersion(service, trace) ?? void 0;
  const latestVersion = getLatestVersion(service, trace) ?? void 0;
  if (!currentVersion) {
    return { latestVersion };
  }
  console.log(createStepMessage("version-current", service, `v${currentVersion}`));
  if (!latestVersion) {
    console.log(createStepMessage("version-latest-unavailable", service, `\uD604\uC7AC v${currentVersion}`));
    return { currentVersion };
  }
  if (!isVersionOutdated(currentVersion, latestVersion)) {
    console.log(createStepMessage("version-ok", service, `v${currentVersion}`));
    return { currentVersion, latestVersion };
  }
  console.log(createStepMessage("version-updating", service, `${currentVersion} -> ${latestVersion}`));
  const upgraded = upgradeServiceCli(service, trace);
  if (upgraded) {
    const newVersion = getInstalledVersion(service, trace) ?? latestVersion;
    console.log(createStepMessage("version-update-ok", service, `v${newVersion}`));
    return { currentVersion: newVersion, latestVersion };
  }
  console.log(
    createStepMessage("version-update-failed", service, `\uD604\uC7AC v${currentVersion}, \uCD5C\uC2E0 v${latestVersion}`)
  );
  return { currentVersion, latestVersion };
}

// src/platform/ai-services/internal/service-health-check.ts
function validateServiceHealth(service, parsedArgs, trace) {
  trace("health-check:validate:start", service);
  if (parsedArgs.testMode) {
    trace("health-check:validate:skip:test-mode");
    return {
      message: "[TEST MODE] \uD5EC\uC2A4\uCCB4\uD06C\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4.",
      ok: true,
      service,
      status: "ready"
    };
  }
  const result = runServiceHealthCheck(service, trace);
  trace("health-check:validate:end", `${service} status=${result.status} ok=${result.ok}`);
  if (!result.ok) {
    console.log("");
    console.log(result.message);
    console.log("");
  }
  return result;
}

export { validateServiceHealth };
