var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { asWorkspaceBackendError } from "./backends/errors";
import { hashQueryText } from "./textHash";
import { normalizeQueryFilename } from "./normalizeQueryFilename";
function normalizeFolderPath(folderPath) {
    if (!folderPath)
        return "";
    const trimmed = folderPath.trim();
    if (!trimmed)
        return "";
    return trimmed.replace(/^\/+/, "").replace(/\/+$/, "");
}
function buildQueryId(folderPath, filename) {
    const normalizedFolder = normalizeFolderPath(folderPath);
    const normalizedFilename = normalizeQueryFilename(filename);
    return normalizedFolder ? `${normalizedFolder}/${normalizedFilename}` : normalizedFilename;
}
function uuidV4() {
    const cryptoObj = globalThis.crypto;
    if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.randomUUID)
        return cryptoObj.randomUUID();
    const rnds = new Uint8Array(16);
    if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.getRandomValues) {
        cryptoObj.getRandomValues(rnds);
    }
    else {
        for (let i = 0; i < rnds.length; i++)
            rnds[i] = Math.floor(Math.random() * 256);
    }
    rnds[6] = (rnds[6] & 0x0f) | 0x40;
    rnds[8] = (rnds[8] & 0x3f) | 0x80;
    const hex = Array.from(rnds, (b) => b.toString(16).padStart(2, "0")).join("");
    return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
function mintSparqlManagedQueryIri(workspaceIri) {
    return `${workspaceIri.trim()}_mq_${uuidV4()}`;
}
function versionRefFromVersionTag(backendType, versionTag) {
    if (!versionTag)
        return undefined;
    if (backendType === "git")
        return { commitSha: versionTag };
    return { managedQueryVersionIri: versionTag };
}
export function saveManagedQuery(input) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a;
        const folderId = normalizeFolderPath(input.folderPath);
        const queryId = input.backendType === "git" ? buildQueryId(input.folderPath, input.filename) : "";
        if (input.backendType === "sparql" && !((_a = input.workspaceIri) === null || _a === void 0 ? void 0 : _a.trim())) {
            throw new Error("workspaceIri is required for SPARQL workspaces");
        }
        const label = (input.name || "").trim();
        if (input.backendType === "sparql" && !label) {
            throw new Error("name is required for SPARQL workspaces");
        }
        const resolvedQueryId = yield (() => __awaiter(this, void 0, void 0, function* () {
            if (input.backendType !== "sparql")
                return queryId;
            try {
                const entries = yield input.backend.listFolder(folderId || undefined);
                const existing = entries.find((e) => e.kind === "query" && e.label.trim().toLowerCase() === label.trim().toLowerCase());
                if (existing === null || existing === void 0 ? void 0 : existing.id)
                    return existing.id;
            }
            catch (_a) {
            }
            return mintSparqlManagedQueryIri(input.workspaceIri || "");
        }))();
        try {
            yield input.backend.writeQuery(resolvedQueryId, input.queryText, Object.assign({ message: input.message, expectedVersionTag: input.expectedVersionTag }, (input.backendType === "sparql"
                ? {
                    label: label || undefined,
                    folderId: folderId || undefined,
                    associatedEndpoint: input.associatedEndpoint || undefined,
                }
                : {})));
        }
        catch (e) {
            const err = asWorkspaceBackendError(e);
            if (err.code === "CONFLICT") {
                const extra = input.backendType === "git"
                    ? " Resolve the conflict externally (e.g., pull/rebase/merge) and then try saving again."
                    : " Refresh the query and try again.";
                throw new Error(`Save conflict.${extra}`);
            }
            throw err;
        }
        const read = yield input.backend.readQuery(resolvedQueryId);
        const lastSavedTextHash = hashQueryText(read.queryText);
        const managedMetadata = {
            workspaceId: input.workspaceId,
            backendType: input.backendType,
            queryRef: input.backendType === "git" ? { path: resolvedQueryId } : { managedQueryIri: resolvedQueryId },
            lastSavedVersionRef: versionRefFromVersionTag(input.backendType, read.versionTag),
            lastSavedTextHash,
        };
        return { queryId: resolvedQueryId, managedMetadata };
    });
}
//# sourceMappingURL=saveManagedQuery.js.map