#!/usr/bin/env node
// Copyright (c) 2026 Hellmai Ltd
// SPDX-License-Identifier: AGPL-3.0-only
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { Command } from 'commander';
import { createHttpControlPlaneSyncPort, parseWorkspaceControlPlaneConfig, } from '@lumenflow/control-plane-sdk';
import { CONFIG_FILES } from '@lumenflow/core/wu-constants';
import { parseYAML } from '@lumenflow/core/wu-yaml';
import { runCLI } from './cli-entry-point.js';
const LOG_PREFIX = '[approval:review]';
const WORKSPACE_PATH = CONFIG_FILES.WORKSPACE_CONFIG;
const DEFAULT_REVIEWER_TYPE = 'user';
const REVIEWER_TYPE_VALUES = new Set(['agent', 'user']);
const DECISION_VALUES = new Set(['approved', 'rejected', 'expired']);
function parseOptions(argv = process.argv) {
    const program = new Command()
        .name('approval-review')
        .description('Resolve a pending approval in the configured control-plane')
        .requiredOption('--id <approvalId>', 'Approval identifier')
        .requiredOption('--decision <decision>', 'Decision: approved, rejected, or expired')
        .option('--reason <reason>', 'Optional decision reason')
        .option('--reviewer-id <id>', 'Reviewer identifier')
        .option('--reviewer-type <type>', 'Reviewer type: agent or user', DEFAULT_REVIEWER_TYPE)
        .option('--workspace-id <id>', 'Override workspace_id from workspace.yaml')
        .option('--json', 'Output JSON response', false)
        .exitOverride();
    try {
        program.parse(argv);
    }
    catch (error) {
        const commanderError = error;
        if (commanderError.code === 'commander.helpDisplayed' ||
            commanderError.code === 'commander.version') {
            process.exit(0);
        }
        throw error;
    }
    const parsed = program.opts();
    const decision = parsed.decision.trim();
    if (!DECISION_VALUES.has(decision)) {
        throw new Error(`Invalid --decision: ${parsed.decision}`);
    }
    const reviewerTypeRaw = (parsed.reviewerType ?? DEFAULT_REVIEWER_TYPE).trim();
    if (!REVIEWER_TYPE_VALUES.has(reviewerTypeRaw)) {
        throw new Error(`Invalid --reviewer-type: ${reviewerTypeRaw}`);
    }
    return {
        approvalId: parsed.id.trim(),
        decision,
        reason: parsed.reason?.trim(),
        reviewerId: parsed.reviewerId?.trim(),
        reviewerType: reviewerTypeRaw,
        workspaceId: parsed.workspaceId?.trim(),
        json: parsed.json ?? false,
    };
}
function resolveApprovalContext(workspaceRoot, environment, workspaceIdOverride) {
    const workspaceFilePath = join(workspaceRoot, WORKSPACE_PATH);
    if (!existsSync(workspaceFilePath)) {
        throw new Error(`Missing workspace config: ${workspaceFilePath}`);
    }
    const workspaceDocument = parseYAML(readFileSync(workspaceFilePath, 'utf-8'));
    const parsed = parseWorkspaceControlPlaneConfig(workspaceDocument);
    const workspaceId = workspaceIdOverride ?? parsed.id;
    if (!workspaceId) {
        throw new Error('workspace.yaml must include id or pass --workspace-id');
    }
    return {
        workspaceId,
        syncPort: createHttpControlPlaneSyncPort(parsed.control_plane, undefined, {
            environment,
        }),
    };
}
function formatResultLine(result) {
    const reasonSuffix = result.decision_reason ? ` (${result.decision_reason})` : '';
    return `${LOG_PREFIX} Updated ${result.approval_id} -> ${result.status}${reasonSuffix}`;
}
export async function runApprovalReview(options, input = {}) {
    const { workspaceId, syncPort } = resolveApprovalContext(input.workspaceRoot ?? process.cwd(), input.environment ?? process.env, options.workspaceId);
    if (!syncPort.resolveApproval) {
        throw new Error('Control-plane adapter does not support resolveApproval');
    }
    const payload = {
        workspace_id: workspaceId,
        approval_id: options.approvalId,
        decision: options.decision,
        reviewer_type: options.reviewerType,
        ...(options.reason ? { reason: options.reason } : {}),
        ...(options.reviewerId ? { reviewer_id: options.reviewerId } : {}),
    };
    return syncPort.resolveApproval(payload);
}
export async function main(argv = process.argv) {
    const options = parseOptions(argv);
    const result = (await runApprovalReview(options));
    if (options.json) {
        console.log(JSON.stringify(result, null, 2));
        return;
    }
    console.log(formatResultLine(result));
}
if (import.meta.main) {
    void runCLI(main);
}
//# sourceMappingURL=approval-review.js.map