"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runDetachCommand = runDetachCommand;
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const control_plane_config_1 = require("../config/control-plane-config");
const fs_errors_1 = require("../core/fs-errors");
const file_readers_1 = require("../core/file-readers");
const tracked_project_1 = require("../core/tracked-project");
const catalog_1 = require("../i18n/catalog");
const repo_registry_1 = require("../core/repo-registry");
const service_state_1 = require("../core/service-state");
const locale_1 = require("./locale");
const shared_1 = require("./shared");
const install_1 = require("./service/install");
const prompts_1 = require("./prompts");
const default_issue_workspace_manager_1 = require("../workspaces/default-issue-workspace-manager");
async function runDetachCommand(cwd, options, deps = {}) {
    const targetCwd = node_path_1.default.resolve(cwd, options.cwd ?? ".");
    const locale = await (0, locale_1.loadCommandLocale)(targetCwd);
    const targetRepo = await discoverCurrentRepo(targetCwd, options.homeDirectory);
    if (!targetRepo) {
        console.log((0, catalog_1.translate)(locale, "detach.command.notRegistered"));
        return 0;
    }
    if (options.purge &&
        !(await (0, prompts_1.confirmIfInteractive)(deps.prompter ?? (0, prompts_1.createCliPrompter)({ locale }), {
            label: (0, catalog_1.translate)(locale, options.force
                ? "detach.command.confirm.purgeForce"
                : "detach.command.confirm.purge"),
            onCanceled: () => console.log((0, catalog_1.translate)(locale, "detach.command.canceled")),
        }))) {
        return 1;
    }
    const serviceWasRunning = options.purge === true &&
        (await (deps.getLiveServiceState ?? service_state_1.getLiveServiceState)(options.homeDirectory)) !== null;
    let serviceStoppedForPurge = false;
    try {
        if (serviceWasRunning) {
            await (deps.runServiceDisable ?? install_1.runServiceDisableCommand)(options.homeDirectory, { ...deps, cwd: targetCwd, quiet: true });
            serviceStoppedForPurge = true;
        }
        const result = await (0, repo_registry_1.detachRepo)({
            repositoryHost: targetRepo.repositoryHost,
            ticketTracker: targetRepo.ticketTracker,
            cwd: targetCwd,
        }, options.homeDirectory);
        if (result.kind === "conflict") {
            throw new Error((0, catalog_1.translate)(locale, "detach.command.conflict", {
                repo: (0, tracked_project_1.formatTrackedProjectRef)(targetRepo, locale),
                registeredCwd: result.existing.cwd,
                cwd: targetCwd,
            }));
        }
        if (result.kind === "missing") {
            console.log((0, catalog_1.translate)(locale, "detach.command.notRegistered"));
            return 0;
        }
        console.log((0, catalog_1.translate)(locale, "detach.command.detached", {
            repo: (0, tracked_project_1.formatTrackedProjectRef)(targetRepo, locale),
        }));
        if (!options.purge) {
            return 0;
        }
        const removedPaths = [];
        const skippedPaths = [];
        const configResult = await maybeRemoveConfigFile(targetCwd, options.force ?? false);
        if (configResult === "removed") {
            removedPaths.push((0, control_plane_config_1.getConfigPath)(targetCwd));
        }
        if (configResult === "skipped") {
            skippedPaths.push((0, control_plane_config_1.getConfigPath)(targetCwd));
        }
        const assetResult = await (0, shared_1.purgeRepositoryAssets)(targetCwd, options.force ? { force: true } : {});
        removedPaths.push(...assetResult.removedPaths);
        skippedPaths.push(...assetResult.skippedPaths);
        const workspaceRoot = (0, default_issue_workspace_manager_1.getProjectWorkspaceRoot)(targetRepo, options.homeDirectory);
        if (await (0, file_readers_1.pathExists)(workspaceRoot)) {
            await (0, promises_1.rm)(workspaceRoot, { recursive: true, force: true });
            removedPaths.push(workspaceRoot);
        }
        if (removedPaths.length > 0) {
            console.log((0, catalog_1.translate)(locale, "detach.command.purged", {
                count: removedPaths.length,
            }));
        }
        if (skippedPaths.length > 0) {
            console.log((0, catalog_1.translate)(locale, "detach.command.skippedModified", {
                count: skippedPaths.length,
            }));
        }
        return 0;
    }
    finally {
        if (serviceStoppedForPurge) {
            await (deps.runServiceInstall ??
                install_1.runServiceInstallCommandWithoutCurrentRepoRegistration)(options.homeDirectory, {
                ...deps,
                cwd: targetCwd,
                quiet: true,
            });
        }
    }
}
async function discoverCurrentRepo(cwd, homeDirectory) {
    const registry = await (0, repo_registry_1.loadRepoRegistry)(homeDirectory);
    const byCwd = registry.repos.find((entry) => node_path_1.default.resolve(entry.cwd) === node_path_1.default.resolve(cwd));
    if (byCwd) {
        return {
            repositoryHost: byCwd.repositoryHost,
            ticketTracker: byCwd.ticketTracker,
        };
    }
    try {
        const config = await (0, control_plane_config_1.loadConfig)(cwd);
        return {
            repositoryHost: config.repositoryHost,
            ticketTracker: config.ticketTracker,
        };
    }
    catch {
        return null;
    }
}
async function maybeRemoveConfigFile(cwd, force) {
    const configPath = (0, control_plane_config_1.getConfigPath)(cwd);
    const text = await (0, file_readers_1.readTextFileIfExists)(configPath);
    if (text === null) {
        return "missing";
    }
    try {
        if (!force) {
            const parsed = JSON.parse(text);
            const normalized = control_plane_config_1.controlPlaneConfigSchema.parse(parsed);
            const canonicalText = (0, control_plane_config_1.formatConfigFile)(normalized);
            if (text !== canonicalText) {
                return "skipped";
            }
        }
        await (0, promises_1.rm)(configPath, { force: true });
        return "removed";
    }
    catch (error) {
        if ((0, fs_errors_1.isZodParseError)(error)) {
            return force ? await forceRemove(configPath) : "skipped";
        }
        throw error;
    }
}
async function forceRemove(configPath) {
    await (0, promises_1.rm)(configPath, { force: true });
    return "removed";
}
