/*
 * 文件定位：ToolabilityPool / TAP 高级工具系统 / Office 工具集合 / 文档工具。
 * 核心目的：提供 办公文档基础工具 / 文档工具 中的“编辑文档”基础能力原语。
 * 能力要求1：需要定义该能力的输入、输出、错误、权限需求和可观测事件。
 * 能力要求2：这些 Office 能力由 TAP 高级工具系统承接，不再作为 baseTool 完成目标。
 * 能力要求3：TAP 负责 Office 能力的治理、审批、组合和专业能力库承接。
 * 边界：承接 Office 高级工具能力，不回写到 agentCore baseTools。
 * 对接：通过 TAP 复用转交与 runtime 官方模块桥接接通，并保留治理、审批和审计边界。
 * 实现提示：先补稳定类型契约、最小可测行为和清晰错误边界，再接入真实执行逻辑。
 */
export const officeDocEditDescriptor = {
    toolId: "office.docEdit",
    capability: "edit-document",
    route: "toolabilityPool.officeBase.documentations",
    defaultDryRun: true,
    unsafeSideEffects: true,
    tapOwnsApproval: true,
    permissionsRequired: ["filesystem:read", "filesystem:write", "office:document:edit"],
};
function cleanList(values) {
    return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))];
}
function dryRunEnabled(context) {
    return context?.dryRun !== false;
}
function invocationId(context) {
    return context?.invocationId?.trim() || "office.docEdit:dry-run";
}
function auditEvent(type, context, documentPath, metadata) {
    return {
        type,
        toolId: officeDocEditDescriptor.toolId,
        invocationId: invocationId(context),
        dryRun: dryRunEnabled(context),
        documentPath,
        metadata: {
            ...(context?.auditMetadata ?? {}),
            ...(metadata ?? {}),
        },
    };
}
function failure(code, message, boundary, context, documentPath) {
    return {
        ok: false,
        toolId: officeDocEditDescriptor.toolId,
        error: { code, message, boundary, publicSafe: true },
        audit: [auditEvent("agentCore.basicTool.office.docEdit.rejected", context, documentPath, { code })],
        events: ["basicTool.office.docEdit.rejected"],
    };
}
function normalizeRoot(root) {
    const trimmed = root.trim();
    return trimmed === "/" ? trimmed : trimmed.replace(/\/+$/, "");
}
function hasUnsafePathSegments(value) {
    return value.includes("\0") || value.split("/").some((segment) => segment === "..");
}
function normalizeDocumentPath(documentPath, context) {
    const normalized = documentPath?.trim() ?? "";
    if (normalized.length === 0) {
        return failure("MISSING_DOCUMENT_PATH", "office.docEdit requires target.documentPath", "input", context, documentPath);
    }
    if (hasUnsafePathSegments(normalized)) {
        return failure("UNSAFE_DOCUMENT_PATH", "office.docEdit document paths must not contain traversal or NUL segments", "scope", context, normalized);
    }
    return normalized;
}
function normalizeOptionalDocumentPath(documentPath, context) {
    const normalized = documentPath?.trim() ?? "";
    if (normalized.length === 0) {
        return undefined;
    }
    if (hasUnsafePathSegments(normalized)) {
        return failure("UNSAFE_DOCUMENT_PATH", "office.docEdit output paths must not contain traversal or NUL segments", "scope", context, normalized);
    }
    return normalized;
}
function ensureScope(target, context) {
    const allowedRoots = cleanList(context?.allowedDocumentRoots).map(normalizeRoot);
    if (allowedRoots.length === 0) {
        return undefined;
    }
    const paths = [target.documentPath, target.outputPath].filter((value) => value !== undefined);
    const outside = paths.find((candidate) => !allowedRoots.some((root) => candidate === root || candidate.startsWith(`${root}/`)));
    if (outside === undefined) {
        return undefined;
    }
    return failure("DOCUMENT_PATH_OUTSIDE_SCOPE", "office.docEdit target document is outside the allowed document roots", "scope", context, outside);
}
function ensurePermissions(documentPath, context) {
    const granted = cleanList(context?.grantedPermissions);
    if (granted.length === 0) {
        return undefined;
    }
    const missing = officeDocEditDescriptor.permissionsRequired.filter((permission) => !granted.includes(permission));
    if (missing.length === 0) {
        return undefined;
    }
    return failure("PERMISSION_DENIED", `office.docEdit is missing permissions: ${missing.join(", ")}`, "permission", context, documentPath);
}
function ensureDryRunOnly(documentPath, context) {
    if (dryRunEnabled(context)) {
        return undefined;
    }
    return failure("REAL_EXECUTION_BLOCKED", "office.docEdit only returns a guarded dry-run plan in the first implementation", "contract", context, documentPath);
}
function normalizeReplaceTextOperation(operation, context, documentPath) {
    const targetText = operation.targetText?.trim() ?? "";
    if (targetText.length === 0 || operation.replacementText === undefined) {
        return failure("INVALID_EDIT_OPERATION", "office.docEdit replaceText operations require targetText and replacementText", "input", context, documentPath);
    }
    const occurrence = operation.occurrence ?? "first";
    if (occurrence !== "first" && occurrence !== "all") {
        return failure("INVALID_EDIT_OPERATION", "office.docEdit replaceText occurrence must be first or all", "input", context, documentPath);
    }
    return {
        kind: "replaceText",
        targetText,
        replacementText: operation.replacementText,
        occurrence,
    };
}
function normalizeInsertTextOperation(operation, context, documentPath) {
    const locator = operation.locator?.trim() ?? "";
    const text = operation.text ?? "";
    if (locator.length === 0 || text.length === 0) {
        return failure("INVALID_EDIT_OPERATION", "office.docEdit insertText operations require locator and text", "input", context, documentPath);
    }
    const position = operation.position ?? "after";
    if (position !== "before" && position !== "after") {
        return failure("INVALID_EDIT_OPERATION", "office.docEdit insertText position must be before or after", "input", context, documentPath);
    }
    return {
        kind: "insertText",
        locator,
        text,
        position,
    };
}
function normalizeDeleteRangeOperation(operation, context, documentPath) {
    const locator = operation.locator?.trim() ?? "";
    if (locator.length === 0) {
        return failure("INVALID_EDIT_OPERATION", "office.docEdit deleteRange operations require locator", "input", context, documentPath);
    }
    return {
        kind: "deleteRange",
        locator,
    };
}
function normalizeOperations(operations, context, documentPath) {
    if (operations === undefined || operations.length === 0) {
        return failure("MISSING_EDIT_OPERATIONS", "office.docEdit requires at least one target.operations entry", "input", context, documentPath);
    }
    const normalized = [];
    for (const operation of operations) {
        if (operation.kind === "replaceText") {
            const next = normalizeReplaceTextOperation(operation, context, documentPath);
            if ("ok" in next) {
                return next;
            }
            normalized.push(next);
            continue;
        }
        if (operation.kind === "insertText") {
            const next = normalizeInsertTextOperation(operation, context, documentPath);
            if ("ok" in next) {
                return next;
            }
            normalized.push(next);
            continue;
        }
        if (operation.kind === "deleteRange") {
            const next = normalizeDeleteRangeOperation(operation, context, documentPath);
            if ("ok" in next) {
                return next;
            }
            normalized.push(next);
            continue;
        }
        return failure("INVALID_EDIT_OPERATION", "office.docEdit operations must be replaceText, insertText, or deleteRange", "input", context, documentPath);
    }
    return normalized;
}
function normalizeTarget(target, context) {
    const documentPath = normalizeDocumentPath(target?.documentPath, context);
    if (typeof documentPath !== "string") {
        return documentPath;
    }
    const outputPath = normalizeOptionalDocumentPath(target?.outputPath, context);
    if (outputPath !== undefined && typeof outputPath !== "string") {
        return outputPath;
    }
    const operations = normalizeOperations(target?.operations, context, documentPath);
    if ("ok" in operations) {
        return operations;
    }
    return {
        documentPath,
        operations,
        outputPath,
    };
}
export function planOfficeDocEdit(request = {}) {
    const target = normalizeTarget(request.target, request.context);
    if ("ok" in target) {
        return target;
    }
    const scopeFailure = ensureScope(target, request.context);
    if (scopeFailure !== undefined) {
        return scopeFailure;
    }
    const permissionFailure = ensurePermissions(target.documentPath, request.context);
    if (permissionFailure !== undefined) {
        return permissionFailure;
    }
    const realExecutionFailure = ensureDryRunOnly(target.documentPath, request.context);
    if (realExecutionFailure !== undefined) {
        return realExecutionFailure;
    }
    return {
        ok: true,
        toolId: officeDocEditDescriptor.toolId,
        output: {
            kind: "agentCore.basicTool.office.docEdit",
            target,
            dryRun: true,
            executionBlocked: true,
            unsafeSideEffects: true,
            permissionsRequired: officeDocEditDescriptor.permissionsRequired,
            editPlan: {
                editor: "office-document-editor-v1",
                wouldMutateDocument: true,
                operationCount: target.operations.length,
                patchEnvelope: {
                    appliedOperations: 0,
                    conflicts: [],
                },
            },
        },
        audit: [
            auditEvent("agentCore.basicTool.office.docEdit.dryRun", request.context, target.documentPath, {
                operationCount: target.operations.length,
                outputPath: target.outputPath,
            }),
        ],
        events: ["basicTool.office.docEdit.dryRun"],
    };
}
