"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.previewStructuredTaskPairCreationSync = previewStructuredTaskPairCreationSync;
exports.applyStructuredTaskPairCreationSync = applyStructuredTaskPairCreationSync;
exports.collectCreationPreconditions = collectCreationPreconditions;
exports.dedupePreconditions = dedupePreconditions;
exports.collectExistingWorkIds = collectExistingWorkIds;
// Structured and governed overview plus task-pair creation orchestration.
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const mutation_preconditions_1 = require("../filesystem/mutation-preconditions");
const repository_transaction_1 = require("../filesystem/repository-transaction");
const canonical_write_target_1 = require("../paths/canonical-write-target");
const ordered_root_identity_1 = require("../planning/ordered-root-identity");
const planning_document_utils_1 = require("../planning/planning-document-utils");
const policy_resolution_1 = require("../planning/policy-resolution");
const structured_task_plan_1 = require("../planning/structured-task-plan");
const spec_readiness_1 = require("../spec-readiness");
const creation_overview_1 = require("./creation-overview");
const governed_overview_1 = require("./governed-overview");
const task_rendering_1 = require("./task-rendering");
function previewStructuredTaskPairCreationSync(request) {
    const repositoryRoot = (0, governed_overview_1.requireRepositoryRoot)(request.repositoryRoot);
    const overviewPath = (0, task_rendering_1.requireRepositoryRelativeInput)(request.overviewPath, 'Structured overview path');
    const overviewTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, overviewPath);
    if (!overviewTarget.exists || !node_fs_1.default.statSync(overviewTarget.runtimePath).isFile()) {
        throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured overview '${overviewPath}' does not exist as a canonical file.`);
    }
    const overviewText = node_fs_1.default.readFileSync(overviewTarget.runtimePath, 'utf8');
    const overview = (0, governed_overview_1.parseStructuredOverview)(overviewText, overviewTarget.repositoryRelativePath);
    const normalizedTasks = (0, governed_overview_1.normalizeStructuredTaskInputs)(request.tasks);
    const taskPlan = (0, structured_task_plan_1.parseStructuredTaskPlan)(overviewText);
    const invalidDeclaration = taskPlan.declarations.find((declaration) => declaration.mappingStatus === 'invalid');
    if (invalidDeclaration !== undefined) {
        throw new creation_overview_1.StructuredWorkCreationError('invalid-request', invalidDeclaration.issues.map((issue) => issue.message).join(' '));
    }
    const workRoot = node_path_1.default.posix.dirname(overviewTarget.repositoryRelativePath);
    const taskCollectionPath = node_path_1.default.posix.join(workRoot, 'tasks');
    let taskInventory;
    let sequenceAllocations;
    try {
        taskInventory = (0, ordered_root_identity_1.inspectStructuredTaskCollectionSync)({
            repositoryRoot,
            collectionPath: taskCollectionPath,
        });
        (0, governed_overview_1.validateStructuredTaskGraph)(normalizedTasks, taskInventory.entries.map((entry) => entry.taskId));
        sequenceAllocations = (0, ordered_root_identity_1.allocateStructuredTaskSequences)({
            inventory: taskInventory,
            taskIds: normalizedTasks.map((task) => task.taskId),
        });
        for (const allocation of sequenceAllocations) {
            const declaration = taskPlan.declarations.find((candidate) => candidate.mappingStatus === 'valid' && candidate.taskId === allocation.taskId);
            if (declaration !== undefined &&
                (declaration.sequence !== allocation.sequence ||
                    declaration.orderedTaskRootName !== allocation.orderedTaskRootName)) {
                throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured Task Plan maps task_id '${allocation.taskId}' to sequence ${declaration.sequence} and ordered root '${declaration.orderedTaskRootName}', but work task create would allocate sequence ${allocation.sequence} and '${allocation.orderedTaskRootName}'. Create tasks in the declared sequence or correct the overview before retrying.`);
            }
        }
    }
    catch (error) {
        throw (0, task_rendering_1.normalizeOrderedRootCreationError)(error);
    }
    const allocationByTaskId = new Map(sequenceAllocations.map((entry) => [entry.taskId, entry]));
    const existingDirectoryByTaskId = new Map(taskInventory.entries.map((entry) => [entry.taskId, entry.basename]));
    const taskTemplate = (0, task_rendering_1.readRequiredTemplate)(repositoryRoot, '.day-shift/templates/task-definition.md');
    const summaryTemplate = (0, task_rendering_1.readRequiredTemplate)(repositoryRoot, '.day-shift/templates/implementation-summary.md');
    const writes = [];
    const preconditions = [
        (0, mutation_preconditions_1.captureContentRevisionPreconditionSync)(overviewTarget),
        ...taskInventory.artifactPaths.map((artifactPath) => (0, mutation_preconditions_1.captureContentRevisionPreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, artifactPath))),
    ];
    let sourceProjectReviewPath = null;
    if (request.sourceProjectReviewPath !== undefined) {
        sourceProjectReviewPath = (0, task_rendering_1.requireRepositoryRelativeInput)(request.sourceProjectReviewPath, 'Structured project review path');
        if (sourceProjectReviewPath !== node_path_1.default.posix.join(workRoot, 'project-review.md')) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured follow-up source must be '${node_path_1.default.posix.join(workRoot, 'project-review.md')}'.`);
        }
        const reviewTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, sourceProjectReviewPath);
        if (!reviewTarget.exists || !node_fs_1.default.statSync(reviewTarget.runtimePath).isFile()) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured project review '${sourceProjectReviewPath}' does not exist as a canonical file.`);
        }
        const reviewDocument = (0, planning_document_utils_1.parseMarkdownFrontMatter)(node_fs_1.default.readFileSync(reviewTarget.runtimePath, 'utf8'));
        if ((0, planning_document_utils_1.readTopLevelField)(reviewDocument.frontMatterLines, 'artifact_type') !== 'project_review' ||
            (0, planning_document_utils_1.readTopLevelField)(reviewDocument.frontMatterLines, 'work_id') !== overview.workId) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured project review '${sourceProjectReviewPath}' does not match work '${overview.workId}'.`);
        }
        preconditions.push((0, mutation_preconditions_1.captureContentRevisionPreconditionSync)(reviewTarget));
    }
    for (const specification of overview.specifications) {
        const specTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, specification.specPath);
        if (!specTarget.exists || !node_fs_1.default.statSync(specTarget.runtimePath).isFile()) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured overview specification '${specification.specId}' is missing at '${specification.specPath}'.`);
        }
        const observed = (0, mutation_preconditions_1.captureContentRevisionPreconditionSync)(specTarget);
        if (observed.expectedRevision !== (0, task_rendering_1.normalizeRecordedRevision)(specification.revision)) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured overview specification '${specification.specId}' no longer matches revision '${specification.revision}'. Refresh or recertify the overview.`);
        }
        preconditions.push(observed);
    }
    const generatedAt = new Date().toISOString();
    const taskEntries = normalizedTasks.map((task) => {
        const allocation = allocationByTaskId.get(task.taskId);
        const taskRoot = node_path_1.default.posix.join(taskCollectionPath, allocation.orderedTaskRootName);
        const taskDefinitionTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, node_path_1.default.posix.join(taskRoot, 'task-definition.md'));
        const summaryTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, node_path_1.default.posix.join(taskRoot, 'implementation-summary.md'));
        if (taskDefinitionTarget.exists || summaryTarget.exists) {
            throw new creation_overview_1.StructuredWorkCreationError('destination-conflict', `Structured task '${task.taskId}' already has a canonical pair destination.`);
        }
        const policy = (0, policy_resolution_1.resolveIndependentTaskPolicy)({
            agentMode: {
                ...request.agentModeResolution,
                task: task.agentMode,
                parent: overview.defaultAgentMode,
                project: request.agentModeResolution?.project,
                repository: request.agentModeResolution?.repository,
            },
            evidenceProfile: {
                ...request.evidenceProfileResolution,
                task: task.evidenceProfile,
                parent: overview.defaultEvidenceProfile,
                project: request.evidenceProfileResolution?.project,
                repository: request.evidenceProfileResolution?.repository,
            },
        });
        const entry = {
            taskId: task.taskId,
            title: task.title,
            sequence: allocation.sequence,
            sequencePrefix: allocation.sequencePrefix,
            orderedTaskRootName: allocation.orderedTaskRootName,
            dependencies: task.dependencies,
            agentMode: policy.agentMode.value,
            agentModeSource: policy.agentMode.source,
            evidenceProfile: policy.evidenceProfile.value,
            evidenceProfileSource: policy.evidenceProfile.source,
            taskDefinitionPath: taskDefinitionTarget.repositoryRelativePath,
            implementationSummaryPath: summaryTarget.repositoryRelativePath,
        };
        const dependencyPaths = task.dependencies.map((dependency) => {
            const requested = allocationByTaskId.get(dependency)?.orderedTaskRootName;
            const existing = existingDirectoryByTaskId.get(dependency);
            const directory = requested ?? existing;
            if (directory === undefined) {
                throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Structured task '${task.taskId}' dependency '${dependency}' is not active.`);
            }
            return node_path_1.default.posix.join(taskCollectionPath, directory, 'task-definition.md');
        });
        writes.push({
            path: entry.taskDefinitionPath,
            contents: (0, task_rendering_1.renderStructuredTaskDefinition)(taskTemplate, {
                overview,
                overviewPath: overviewTarget.repositoryRelativePath,
                entry,
                task,
                dependencyPaths,
                generatedAt,
                sourceProjectReviewPath,
            }),
        }, {
            path: entry.implementationSummaryPath,
            contents: (0, task_rendering_1.renderStructuredImplementationSummary)(summaryTemplate, {
                overview,
                overviewPath: overviewTarget.repositoryRelativePath,
                entry,
                task,
                generatedAt,
            }),
        });
        preconditions.push((0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)(taskDefinitionTarget), (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)(summaryTarget));
        return entry;
    });
    const expected = dedupePreconditions(preconditions).map((precondition) => ({
        path: precondition.repositoryRelativePath,
        kind: precondition.kind,
        expectedState: precondition.kind === 'content-revision' ? precondition.expectedRevision : precondition.expectedPresence,
    }));
    const result = {
        workflowLevel: 'structured',
        workId: overview.workId,
        overviewPath: overviewTarget.repositoryRelativePath,
        specifications: overview.specifications,
        tasks: taskEntries,
        taskInventoryFingerprint: taskInventory.fingerprint,
        expected,
        intendedPaths: writes.map((write) => write.path),
        changedPaths: [],
        writeOutcome: 'previewed',
        transactionId: null,
        conflicts: [],
        recoveryPath: null,
        failure: null,
        nextAction: 'Apply this preview to create the ordered direct Structured task pairs.',
    };
    creation_overview_1.taskPairPlans.set(result, {
        repositoryRoot,
        writes,
        preconditions: dedupePreconditions(preconditions),
        inventoryCollectionPath: taskCollectionPath,
        inventoryFingerprint: taskInventory.fingerprint,
    });
    return result;
}
function applyStructuredTaskPairCreationSync(preview, options = {}) {
    const plan = creation_overview_1.taskPairPlans.get(preview);
    if (plan === undefined || preview.writeOutcome !== 'previewed') {
        throw new creation_overview_1.StructuredWorkCreationError('stale-preview', 'Structured task-pair apply requires the original unused in-process preview. Refresh the preview.');
    }
    creation_overview_1.taskPairPlans.delete(preview);
    let observedFingerprint;
    try {
        observedFingerprint = (0, ordered_root_identity_1.inspectStructuredTaskCollectionSync)({
            repositoryRoot: plan.repositoryRoot,
            collectionPath: plan.inventoryCollectionPath,
        }).fingerprint;
    }
    catch {
        observedFingerprint = 'invalid-inventory';
    }
    if (observedFingerprint !== plan.inventoryFingerprint) {
        return {
            ...preview,
            writeOutcome: 'conflict',
            conflicts: [(0, task_rendering_1.inventoryConflict)(plan.inventoryCollectionPath, plan.inventoryFingerprint, observedFingerprint)],
            nextAction: 'Refresh the Structured task-pair preview after the parent-local task inventory changed.',
        };
    }
    const transaction = (0, repository_transaction_1.executeRepositoryTransactionSync)(plan.repositoryRoot, { writes: plan.writes, preconditions: plan.preconditions }, options.transaction);
    return {
        ...preview,
        changedPaths: transaction.entries.slice(0, transaction.canonicalWrites).map((entry) => entry.path),
        writeOutcome: transaction.outcome,
        transactionId: transaction.transactionId,
        conflicts: transaction.conflicts,
        recoveryPath: transaction.outcome === 'incomplete' ? transaction.transactionPath : null,
        failure: transaction.failure,
        nextAction: transaction.outcome === 'committed'
            ? 'Review readiness for the created Structured tasks.'
            : (0, governed_overview_1.nextActionForOutcome)(transaction.outcome, 'structured'),
    };
}
function collectCreationPreconditions(repositoryRoot, specifications, overviewPath) {
    const preconditions = [
        (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, overviewPath)),
    ];
    for (const specification of specifications) {
        const resolution = (0, spec_readiness_1.resolveSpecificationPlanningReadinessSync)(repositoryRoot, specification.specPath);
        if (!resolution.eligible || resolution.currentSpecRevision !== specification.revision) {
            throw new creation_overview_1.StructuredWorkCreationError('invalid-request', `Specification '${specification.specId}' changed while the creation preview was assembled.`);
        }
        preconditions.push((0, mutation_preconditions_1.captureContentRevisionPreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, resolution.specPath)));
        preconditions.push((0, mutation_preconditions_1.captureContentRevisionPreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, resolution.dispositionPath)));
        if (resolution.reviewPath !== null) {
            preconditions.push((0, mutation_preconditions_1.captureContentRevisionPreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, resolution.reviewPath)));
        }
    }
    return dedupePreconditions(preconditions);
}
function dedupePreconditions(preconditions) {
    const observed = new Set();
    return preconditions.filter((precondition) => {
        const key = `${precondition.kind}:${precondition.repositoryRelativePath}`;
        if (observed.has(key))
            return false;
        observed.add(key);
        return true;
    });
}
function collectExistingWorkIds(repositoryRoot, planningRoot, workflowLevel) {
    const levelRoot = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, node_path_1.default.posix.join(planningRoot.replace(/\\/g, '/'), workflowLevel));
    if (!levelRoot.exists)
        return [];
    if (!node_fs_1.default.statSync(levelRoot.runtimePath).isDirectory()) {
        throw new creation_overview_1.StructuredWorkCreationError('destination-conflict', `${(0, governed_overview_1.workflowLevelLabel)(workflowLevel)} planning root '${levelRoot.repositoryRelativePath}' is not a directory.`);
    }
    return node_fs_1.default
        .readdirSync(levelRoot.runtimePath, { withFileTypes: true })
        .filter((entry) => entry.isDirectory())
        .map((entry) => entry.name)
        .sort((left, right) => left.localeCompare(right));
}
