#!/usr/bin/env node
import {
  Confirm
} from "../chunk-N6S7ZRIL.js";
import {
  claudePluginUninstall,
  isClaudeCLIAvailable
} from "../chunk-CJFWO46A.js";
import {
  DRY_RUN_MESSAGES,
  INFO_MESSAGES,
  SUCCESS_MESSAGES
} from "../chunk-2RQYJFKA.js";
import {
  BaseCommand,
  EXIT_CODES
} from "../chunk-LNA6M2IE.js";
import {
  getProjectPluginsDir,
  listPluginNames,
  loadProjectSourceConfig,
  readForkedFromMetadata
} from "../chunk-GFDGYQ6M.js";
import "../chunk-T4EXUIBY.js";
import {
  directoryExists,
  getErrorMessage,
  listDirectories,
  remove
} from "../chunk-C4QI54PN.js";
import {
  CLAUDE_DIR,
  CLAUDE_SRC_DIR,
  CLI_COLORS,
  DEFAULT_BRANDING
} from "../chunk-FTD5Z6QD.js";
import {
  init_esm_shims
} from "../chunk-DHET7RCE.js";

// src/cli/commands/uninstall.tsx
init_esm_shims();
import { Flags } from "@oclif/core";
import { render, Box, Text, useApp } from "ink";
import path from "path";
import { jsx, jsxs } from "react/jsx-runtime";
function collectConfiguredSources(config) {
  if (!config) return [];
  const sources = [];
  if (config.source) {
    sources.push(config.source);
  }
  if (config.sources) {
    for (const entry of config.sources) {
      sources.push(entry.url);
    }
  }
  return sources;
}
async function detectUninstallTarget(projectDir) {
  const pluginsDir = getProjectPluginsDir(projectDir);
  const skillsDir = path.join(projectDir, CLAUDE_DIR, "skills");
  const agentsDir = path.join(projectDir, CLAUDE_DIR, "agents");
  const claudeDir = path.join(projectDir, CLAUDE_DIR);
  const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);
  const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(
    [
      directoryExists(skillsDir),
      directoryExists(agentsDir),
      directoryExists(claudeDir),
      directoryExists(claudeSrcDir),
      loadProjectSourceConfig(projectDir)
    ]
  );
  let pluginNames = [];
  try {
    pluginNames = await listPluginNames(projectDir);
  } catch {
  }
  const configuredSources = collectConfiguredSources(config);
  return {
    hasPlugins: pluginNames.length > 0,
    pluginNames,
    hasLocalSkills,
    hasLocalAgents,
    hasClaudeDir,
    hasClaudeSrcDir,
    pluginsDir,
    skillsDir,
    agentsDir,
    claudeDir,
    claudeSrcDir,
    config,
    configuredSources
  };
}
var UninstallConfirm = ({
  target,
  removeAll,
  onConfirm,
  onCancel
}) => {
  const { exit } = useApp();
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
    /* @__PURE__ */ jsx(Text, { bold: true, children: "The following will be removed:" }),
    /* @__PURE__ */ jsx(Text, { children: " " }),
    target.hasPlugins && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
      /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.ERROR, children: " Plugins:" }),
      /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
        " ",
        target.pluginsDir
      ] })
    ] }),
    (target.hasLocalSkills || target.hasLocalAgents) && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
      /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.ERROR, children: " CLI-managed files:" }),
      target.hasLocalSkills && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
        " ",
        target.skillsDir,
        "/ (matching sources)"
      ] }),
      target.hasLocalAgents && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
        " ",
        target.agentsDir,
        "/ (CLI-compiled)"
      ] })
    ] }),
    removeAll && target.hasClaudeSrcDir && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
      /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.ERROR, children: " Config:" }),
      /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
        " ",
        target.claudeSrcDir,
        "/"
      ] })
    ] }),
    /* @__PURE__ */ jsx(Text, { children: " " }),
    /* @__PURE__ */ jsx(
      Confirm,
      {
        message: "Are you sure you want to uninstall?",
        onConfirm: () => {
          onConfirm();
          exit();
        },
        onCancel: () => {
          onCancel();
          exit();
        },
        defaultValue: false
      }
    )
  ] });
};
async function isDirectoryEmpty(dirPath) {
  const { readdir } = await import("fs/promises");
  try {
    const allEntries = await readdir(dirPath);
    return allEntries.length === 0;
  } catch {
    return true;
  }
}
function skillMatchesConfiguredSource(forkedFromSource, configuredSources) {
  if (!forkedFromSource || configuredSources.length === 0) return false;
  return configuredSources.includes(forkedFromSource);
}
var Uninstall = class _Uninstall extends BaseCommand {
  static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;
  static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;
  static examples = [
    "<%= config.bin %> <%= command.id %>",
    "<%= config.bin %> <%= command.id %> --yes",
    "<%= config.bin %> <%= command.id %> --all",
    "<%= config.bin %> <%= command.id %> --dry-run"
  ];
  static flags = {
    ...BaseCommand.baseFlags,
    yes: Flags.boolean({
      char: "y",
      description: "Skip confirmation prompt",
      default: false
    }),
    all: Flags.boolean({
      description: "Also remove .claude-src/ config directory",
      default: false
    })
  };
  async run() {
    const { flags } = await this.parse(_Uninstall);
    const projectDir = process.cwd();
    this.log("");
    this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);
    this.log("");
    if (flags["dry-run"]) {
      this.log(DRY_RUN_MESSAGES.PREVIEW_NO_FILES_REMOVED);
      this.log("");
    }
    const target = await detectUninstallTarget(projectDir);
    const hasAnythingToRemove = target.hasPlugins || target.hasLocalSkills || target.hasLocalAgents || flags.all && target.hasClaudeSrcDir;
    if (!hasAnythingToRemove) {
      this.warn("Nothing to uninstall.");
      this.log("");
      this.log(INFO_MESSAGES.NOT_INSTALLED);
      this.log("");
      this.log(INFO_MESSAGES.NO_CHANGES_MADE);
      return;
    }
    if (!flags.yes && !flags["dry-run"]) {
      const confirmed = await new Promise((resolve) => {
        const { waitUntilExit } = render(
          /* @__PURE__ */ jsx(
            UninstallConfirm,
            {
              target,
              removeAll: flags.all,
              onConfirm: () => resolve(true),
              onCancel: () => resolve(false)
            }
          )
        );
        waitUntilExit().catch(() => resolve(false));
      });
      if (!confirmed) {
        this.log("");
        this.log("Uninstall cancelled");
        this.exit(EXIT_CODES.CANCELLED);
      }
    } else {
      this.log("The following will be removed:");
      this.log("");
      if (target.hasPlugins) {
        this.log("  Plugins:");
        this.log(`    ${target.pluginsDir}`);
      }
      if (target.hasLocalSkills || target.hasLocalAgents) {
        this.log("  CLI-managed files:");
        if (target.hasLocalSkills) {
          this.log(`    ${target.skillsDir}/ (matching sources)`);
        }
        if (target.hasLocalAgents) {
          this.log(`    ${target.agentsDir}/ (CLI-compiled)`);
        }
      }
      if (flags.all && target.hasClaudeSrcDir) {
        this.log("  Config:");
        this.log(`    ${target.claudeSrcDir}/`);
      }
      this.log("");
    }
    if (flags["dry-run"]) {
      if (target.hasPlugins) {
        this.log(`[dry-run] Would uninstall ${target.pluginNames.length} plugins:`);
        for (const pluginName of target.pluginNames) {
          this.log(`[dry-run]   ${pluginName}`);
        }
      }
      await this.dryRunLocalRemoval(target, flags.all);
      this.log("");
      this.log(DRY_RUN_MESSAGES.COMPLETE_NO_FILES_REMOVED);
      this.log("");
      return;
    }
    if (target.hasPlugins) {
      this.log("Uninstalling plugins...");
      try {
        const cliAvailable = await isClaudeCLIAvailable();
        for (const pluginName of target.pluginNames) {
          if (cliAvailable) {
            try {
              await claudePluginUninstall(pluginName, "project", projectDir);
            } catch {
            }
          }
          const pluginPath = path.join(target.pluginsDir, pluginName);
          await remove(pluginPath);
          this.log(`  Uninstalled plugin '${pluginName}'`);
        }
        this.logSuccess(
          `Uninstalled ${target.pluginNames.length} ${target.pluginNames.length === 1 ? "plugin" : "plugins"}`
        );
      } catch (error) {
        this.log("Plugin uninstall failed");
        this.error(getErrorMessage(error), {
          exit: EXIT_CODES.ERROR
        });
      }
    }
    try {
      await this.removeLocalFiles(target, flags.all);
    } catch (error) {
      this.log("Failed to remove local files");
      this.error(getErrorMessage(error), {
        exit: EXIT_CODES.ERROR
      });
    }
    this.log("");
    this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);
    this.log("");
    this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);
    this.log("");
  }
  /**
   * Selectively removes local files installed by the CLI using config-based matching.
   *
   * - Skills: removes skill dirs whose forked_from.source matches a configured source
   * - Agents: removes agents whose frontmatter name matches a configured agent, or
   *           all agents if config.yaml exists (CLI was used to compile them)
   * - Plugins: removed separately (always)
   * - .claude-src/: only removed with --all flag
   * - .claude/: only removed if empty after selective cleanup
   */
  async removeLocalFiles(target, removeAll) {
    let removedSkillCount = 0;
    let skippedSkillCount = 0;
    if (target.hasLocalSkills) {
      const skillDirNames = await listDirectories(target.skillsDir);
      for (const skillDirName of skillDirNames) {
        const skillDir = path.join(target.skillsDir, skillDirName);
        const forkedFrom = await readForkedFromMetadata(skillDir);
        const shouldRemove = forkedFrom !== null && (skillMatchesConfiguredSource(forkedFrom.source, target.configuredSources) || // Legacy skills without source field are treated as CLI-managed when config exists
        !forkedFrom.source && target.config !== null);
        if (shouldRemove) {
          await remove(skillDir);
          removedSkillCount++;
          this.log(`  Uninstalled skill '${skillDirName}'`);
        } else {
          this.warn(`Skipping '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`);
          skippedSkillCount++;
        }
      }
      if (removedSkillCount > 0) {
        this.logSuccess(
          `Removed ${removedSkillCount} CLI-installed ${removedSkillCount === 1 ? "skill" : "skills"}`
        );
      }
      if (skippedSkillCount === 0 && await directoryExists(target.skillsDir)) {
        if (await isDirectoryEmpty(target.skillsDir)) {
          await remove(target.skillsDir);
        }
      }
    }
    if (target.hasLocalAgents) {
      if (target.config !== null) {
        const { readdir } = await import("fs/promises");
        try {
          const agentFiles = (await readdir(target.agentsDir)).filter((f) => f.endsWith(".md"));
          for (const agentFile of agentFiles) {
            this.log(`  Uninstalled agent '${agentFile.replace(/\.md$/, "")}'`);
          }
        } catch {
        }
        await remove(target.agentsDir);
        this.logSuccess("Removed compiled agents");
      }
    }
    if (removeAll && target.hasClaudeSrcDir) {
      await remove(target.claudeSrcDir);
      this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);
    }
    if (target.hasClaudeDir && await directoryExists(target.claudeDir)) {
      if (await isDirectoryEmpty(target.claudeDir)) {
        await remove(target.claudeDir);
        this.logSuccess(`Removed ${CLAUDE_DIR}/`);
      } else {
        this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);
      }
    }
  }
  async dryRunLocalRemoval(target, removeAll) {
    if (target.hasLocalSkills) {
      const skillDirNames = await listDirectories(target.skillsDir);
      for (const skillDirName of skillDirNames) {
        const skillDir = path.join(target.skillsDir, skillDirName);
        const forkedFrom = await readForkedFromMetadata(skillDir);
        const shouldRemove = forkedFrom !== null && (skillMatchesConfiguredSource(forkedFrom.source, target.configuredSources) || !forkedFrom.source && target.config !== null);
        if (shouldRemove) {
          this.log(`[dry-run] Would remove skill '${skillDirName}'`);
        } else {
          this.log(
            `[dry-run] Would skip '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`
          );
        }
      }
    }
    if (target.hasLocalAgents && target.config !== null) {
      this.log(`[dry-run] Would remove ${target.agentsDir}/`);
    }
    if (removeAll && target.hasClaudeSrcDir) {
      this.log(`[dry-run] Would remove ${target.claudeSrcDir}/`);
    }
    if (target.hasClaudeDir) {
      this.log(`[dry-run] Would remove ${target.claudeDir}/ only if empty after cleanup`);
    }
  }
};
export {
  Uninstall as default
};
//# sourceMappingURL=uninstall.js.map