"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadRepoRegistry = loadRepoRegistry;
exports.writeRepoRegistry = writeRepoRegistry;
exports.registerRepo = registerRepo;
exports.detachRepo = detachRepo;
exports.createEmptyRepoRegistry = createEmptyRepoRegistry;
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const zod_1 = require("zod");
const catalog_1 = require("../i18n/catalog");
const provider_resolution_1 = require("../platform/provider-resolution");
const file_readers_1 = require("./file-readers");
const tracked_project_1 = require("./tracked-project");
const paths_1 = require("./paths");
const REPO_REGISTRY_VERSION = 2;
const repoRegistryEntrySchema = zod_1.z.object({
    repositoryHost: tracked_project_1.repositoryHostProjectRefSchema,
    ticketTracker: tracked_project_1.ticketTrackerProjectRefSchema,
    cwd: zod_1.z.string().min(1),
    enabled: zod_1.z.boolean(),
    addedAt: zod_1.z.string().min(1),
});
const repoRegistrySchema = zod_1.z.object({
    version: zod_1.z.literal(REPO_REGISTRY_VERSION),
    repos: zod_1.z.array(repoRegistryEntrySchema),
});
async function loadRepoRegistry(homeDirectory, locale = catalog_1.DEFAULT_APP_LOCALE) {
    const registryPath = (0, paths_1.getRepoRegistryPath)(homeDirectory);
    const text = await (0, file_readers_1.readTextFileIfExists)(registryPath);
    if (text === null) {
        return createEmptyRepoRegistry();
    }
    const parsed = JSON.parse(text);
    try {
        return repoRegistrySchema.parse(parsed);
    }
    catch {
        throw new Error((0, catalog_1.translate)(locale, "repoRegistry.readFailed", { registryPath }));
    }
}
async function writeRepoRegistry(registry, homeDirectory) {
    const registryPath = (0, paths_1.getRepoRegistryPath)(homeDirectory);
    const normalized = repoRegistrySchema.parse(registry);
    await (0, promises_1.mkdir)(node_path_1.default.dirname(registryPath), { recursive: true });
    await (0, promises_1.writeFile)(registryPath, `${JSON.stringify(normalized, null, 2)}\n`, "utf8");
    return registryPath;
}
async function registerRepo(input, homeDirectory) {
    const registry = await loadRepoRegistry(homeDirectory);
    const normalizedRef = (0, provider_resolution_1.resolveTrackedProjectRef)(toTrackedProjectRef(input)).ref;
    const normalizedCwd = node_path_1.default.resolve(input.cwd);
    const existing = registry.repos.find((entry) => matchesTrackedProject(entry, normalizedRef));
    if (existing) {
        if (node_path_1.default.resolve(existing.cwd) === normalizedCwd) {
            return { kind: "noop", entry: existing };
        }
        return { kind: "conflict", existing };
    }
    const entry = {
        repositoryHost: normalizedRef.repositoryHost,
        ticketTracker: normalizedRef.ticketTracker,
        cwd: normalizedCwd,
        enabled: input.enabled ?? true,
        addedAt: input.addedAt ?? new Date().toISOString(),
    };
    await writeRepoRegistry({
        version: REPO_REGISTRY_VERSION,
        repos: [...registry.repos, entry],
    }, homeDirectory);
    return { kind: "added", entry };
}
async function detachRepo(input, homeDirectory) {
    const registry = await loadRepoRegistry(homeDirectory);
    const normalizedCwd = node_path_1.default.resolve(input.cwd);
    const existing = registry.repos.find((entry) => matchesTrackedProject(entry, input));
    if (!existing) {
        return { kind: "missing" };
    }
    if (node_path_1.default.resolve(existing.cwd) !== normalizedCwd) {
        return { kind: "conflict", existing };
    }
    await writeRepoRegistry({
        version: registry.version,
        repos: registry.repos.filter((entry) => !matchesTrackedProject(entry, input)),
    }, homeDirectory);
    return { kind: "removed", entry: existing };
}
function createEmptyRepoRegistry() {
    return {
        version: REPO_REGISTRY_VERSION,
        repos: [],
    };
}
function matchesTrackedProject(left, right) {
    return ((0, provider_resolution_1.getTrackedProjectKey)(toTrackedProjectRef(left)) ===
        (0, provider_resolution_1.getTrackedProjectKey)(right));
}
function toTrackedProjectRef(input) {
    return tracked_project_1.trackedProjectRefSchema.parse(input);
}
