/**
 * Phase 6 — Stage 4: Deployment Finalization
 *
 * Generates production-ready deployment scripts:
 * - deploy.sh (gcloud CLI commands)
 * - teardown.sh (cleanup script)
 * - env.template (Secret Manager references)
 * - vpc-setup.sh (VPC connector for ERP network)
 * - monitoring.yaml (Cloud Monitoring alert policies)
 *
 * References infra repo patterns for IAM/networking.
 * References integrations repo for webhook/event patterns.
 */
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import { createSpan, endSpan, emitSpan } from '../../phase2/telemetry.js';
// ============================================================================
// Constants
// ============================================================================
const DIR_MODE = 0o700;
const FILE_MODE = 0o600;
const EXEC_MODE = 0o700;
const SCRIPT_HEADER = [
    '#!/usr/bin/env bash',
    '# Generated by Phase 6 pipeline — do not edit manually',
    '#',
    '# This script is deterministic and idempotent.',
    '',
    'set -euo pipefail',
    '',
].join('\n');
function deriveDeploymentVars(context) {
    const registrationStage = context.stageOutputs.get('service-registration');
    let serviceName = 'erp-service';
    let serviceAccount = 'erp-service-sa@PROJECT_ID.iam.gserviceaccount.com';
    let vpcConnector = 'sap-connector';
    let erpAuthScheme = 'api-key';
    let erpSecretNames = ['erp-api-key'];
    let erpEnvVars = ['ERP_BASE_URL', 'ERP_API_KEY'];
    if (registrationStage?.status === 'completed' && registrationStage.data) {
        const data = registrationStage.data;
        const registration = data['registration'];
        if (registration) {
            serviceName = registration['service_name'] ?? serviceName;
            const vpcConfig = registration['vpc_config'];
            if (vpcConfig)
                vpcConnector = vpcConfig['connector_name'] ?? vpcConnector;
            const iamConfig = registration['iam_config'];
            if (iamConfig)
                serviceAccount = iamConfig['service_account'] ?? serviceAccount;
            if (registration['auth_scheme'])
                erpAuthScheme = registration['auth_scheme'];
            if (registration['erp_secret_names'])
                erpSecretNames = registration['erp_secret_names'];
            if (registration['erp_env_vars'])
                erpEnvVars = registration['erp_env_vars'];
        }
    }
    return { serviceName, region: 'us-central1', serviceAccount, vpcConnector, erpAuthScheme, erpSecretNames, erpEnvVars };
}
// ============================================================================
// Script Generators
// ============================================================================
function generateDeployScript(vars, erpSystem) {
    // Build ERP-specific secrets string for --set-secrets
    const secretMappings = vars.erpSecretNames
        .map(name => {
        const envKey = name.toUpperCase().replace(/[^A-Z0-9]/g, '_');
        return `${envKey}=${name}:latest`;
    })
        .join(',');
    return [
        SCRIPT_HEADER,
        `# Deploy ${vars.serviceName} to Cloud Run`,
        `# ERP System: ${erpSystem}`,
        `# Auth Scheme: ${vars.erpAuthScheme}`,
        '',
        'GCP_PROJECT_ID=${GCP_PROJECT_ID:?ERROR: GCP_PROJECT_ID must be set}',
        `GCP_REGION="\${GCP_REGION:-${vars.region}}"`,
        `SERVICE_NAME="\${SERVICE_NAME:-${vars.serviceName}}"`,
        'IMAGE_TAG="${IMAGE_TAG:-latest}"',
        'IMAGE_URL="gcr.io/${GCP_PROJECT_ID}/${SERVICE_NAME}:${IMAGE_TAG}"',
        `SERVICE_ACCOUNT="\${SERVICE_ACCOUNT:-${vars.serviceAccount}}"`,
        `VPC_CONNECTOR="\${VPC_CONNECTOR:-${vars.vpcConnector}}"`,
        '',
        'echo "[1/5] Checking GCP authentication..."',
        'gcloud auth print-identity-token > /dev/null 2>&1 || { echo "Not authenticated."; exit 1; }',
        '',
        'echo "[2/5] Setting project..."',
        'gcloud config set project "${GCP_PROJECT_ID}"',
        '',
        'echo "[3/5] Building container image..."',
        'gcloud builds submit --tag "${IMAGE_URL}" --timeout=600s .',
        '',
        'echo "[4/5] Deploying to Cloud Run..."',
        'gcloud run deploy "${SERVICE_NAME}" \\',
        '  --image "${IMAGE_URL}" \\',
        '  --region "${GCP_REGION}" \\',
        '  --platform managed \\',
        '  --no-allow-unauthenticated \\',
        '  --vpc-connector "${VPC_CONNECTOR}" \\',
        '  --vpc-egress all-traffic \\',
        '  --service-account "${SERVICE_ACCOUNT}" \\',
        ...(secretMappings ? [`  --set-secrets "${secretMappings}" \\`] : []),
        `  --set-env-vars "NODE_ENV=production,PORT=8080,ERP_SYSTEM=${erpSystem}" \\`,
        '  --min-instances 0 --max-instances 10 \\',
        '  --memory 512Mi --cpu 1 --timeout 300 --concurrency 80 \\',
        '  --ingress internal-and-cloud-load-balancing --quiet',
        '',
        'echo "[5/5] Verifying deployment..."',
        'SERVICE_URL=$(gcloud run services describe "${SERVICE_NAME}" --region "${GCP_REGION}" --format "value(status.url)")',
        'echo "Deployed: ${SERVICE_URL}"',
        '',
    ].join('\n');
}
function generateTeardownScript(vars) {
    return [
        SCRIPT_HEADER,
        `# Teardown ${vars.serviceName}`,
        '',
        'GCP_PROJECT_ID=${GCP_PROJECT_ID:?ERROR: GCP_PROJECT_ID must be set}',
        `GCP_REGION="\${GCP_REGION:-${vars.region}}"`,
        `SERVICE_NAME="\${SERVICE_NAME:-${vars.serviceName}}"`,
        '',
        'read -rp "Are you sure you want to delete ${SERVICE_NAME}? (y/N): " CONFIRM',
        'if [[ "${CONFIRM}" != "y" && "${CONFIRM}" != "Y" ]]; then echo "Cancelled."; exit 0; fi',
        '',
        'echo "[1/3] Deleting Cloud Run service..."',
        'gcloud run services delete "${SERVICE_NAME}" --region "${GCP_REGION}" --quiet 2>/dev/null || echo "  Not found."',
        '',
        'echo "[2/3] Cleaning container images..."',
        'gcloud container images list-tags "gcr.io/${GCP_PROJECT_ID}/${SERVICE_NAME}" --format="get(digest)" 2>/dev/null | while read -r DIGEST; do',
        '  gcloud container images delete "gcr.io/${GCP_PROJECT_ID}/${SERVICE_NAME}@${DIGEST}" --quiet --force-delete-tags 2>/dev/null || true',
        'done',
        '',
        'echo "[3/3] Done."',
        '',
    ].join('\n');
}
function generateEnvTemplate(vars, erpSystem) {
    const lines = [
        '# Generated by Phase 6 pipeline',
        `# ERP System: ${erpSystem}`,
        `# Auth Scheme: ${vars.erpAuthScheme}`,
        '',
        `GCP_REGION=${vars.region}`,
        `SERVICE_NAME=${vars.serviceName}`,
        `SERVICE_ACCOUNT=${vars.serviceAccount}`,
        'PORT=8080',
        'NODE_ENV=production',
        `ERP_SYSTEM=${erpSystem}`,
        `VPC_CONNECTOR=${vars.vpcConnector}`,
        '',
        '# ERP-specific environment variables',
    ];
    for (const envVar of vars.erpEnvVars) {
        lines.push(`${envVar}=`);
    }
    // Add secret references for each ERP secret
    lines.push('');
    lines.push('# Secret Manager references');
    for (const secretName of vars.erpSecretNames) {
        const envKey = secretName.toUpperCase().replace(/[^A-Z0-9]/g, '_');
        lines.push(`${envKey}=projects/\${GCP_PROJECT_ID}/secrets/${secretName}/versions/latest`);
    }
    lines.push('');
    return lines.join('\n');
}
function generateVpcSetupScript(vars, infraRepoPath) {
    let infraNote = '';
    if (infraRepoPath) {
        infraNote = `# Follows patterns from: ${infraRepoPath}/modules/networking/\n`;
    }
    return [
        SCRIPT_HEADER,
        `# VPC Connector Setup for ${vars.serviceName}`,
        infraNote,
        'GCP_PROJECT_ID=${GCP_PROJECT_ID:?ERROR: GCP_PROJECT_ID must be set}',
        `GCP_REGION="\${GCP_REGION:-${vars.region}}"`,
        `VPC_CONNECTOR="\${VPC_CONNECTOR:-${vars.vpcConnector}}"`,
        '',
        'gcloud services enable vpcaccess.googleapis.com --project "${GCP_PROJECT_ID}" --quiet',
        'gcloud compute networks vpc-access connectors create "${VPC_CONNECTOR}" \\',
        '  --region "${GCP_REGION}" --network default --range 10.8.0.0/28 \\',
        '  --min-instances 2 --max-instances 10 --machine-type e2-micro \\',
        '  --quiet 2>/dev/null || echo "VPC connector already exists."',
        '',
        'echo "VPC setup complete: ${VPC_CONNECTOR}"',
        '',
    ].join('\n');
}
function generateMonitoringYaml(vars) {
    const sn = vars.serviceName;
    return [
        '# Generated by Phase 6 pipeline',
        `# Alert policies for ${sn}`,
        '',
        'alertPolicies:',
        `  - displayName: "[${sn}] High Error Rate"`,
        '    conditions:',
        '      - displayName: "5xx > 5%"',
        '        conditionThreshold:',
        `          filter: resource.labels.service_name="${sn}" AND metric.labels.response_code_class="5xx"`,
        '          comparison: COMPARISON_GT',
        '          thresholdValue: 0.05',
        '          duration: 300s',
        '',
        `  - displayName: "[${sn}] Elevated Latency"`,
        '    conditions:',
        '      - displayName: "p99 > 5s"',
        '        conditionThreshold:',
        `          filter: resource.labels.service_name="${sn}"`,
        '          comparison: COMPARISON_GT',
        '          thresholdValue: 5000',
        '          duration: 300s',
        '',
    ].join('\n');
}
// ============================================================================
// File writers
// ============================================================================
function writeScript(absPath, content) {
    writeFileSync(absPath, content, { encoding: 'utf-8', mode: EXEC_MODE });
}
function writeArtifact(absPath, content) {
    writeFileSync(absPath, content, { encoding: 'utf-8', mode: FILE_MODE });
}
function resolveInfraRepoPath(platformRepoPaths) {
    const infraPath = platformRepoPaths['infra'];
    if (!infraPath || !existsSync(infraPath))
        return undefined;
    return infraPath;
}
// ============================================================================
// README Generator
// ============================================================================
function generateReadme(vars, erpSystem, context) {
    const serviceName = vars.serviceName;
    const serviceNameUpper = serviceName.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
    const registrationStage = context.stageOutputs.get('service-registration');
    const registration = registrationStage?.data;
    const registrationData = registration?.['registration'];
    const endpoints = registrationData?.['endpoints'] ?? [];
    return [
        `# ${serviceNameUpper}`,
        '',
        '```',
        '┌──────────────────────────────────────────────────────────────┐',
        '│                                                              │',
        `│   ${serviceNameUpper.padEnd(56)}│`,
        '│   Enterprise Service — Generated by Agentics Pipeline       │',
        '│                                                              │',
        '└──────────────────────────────────────────────────────────────┘',
        '```',
        '',
        `![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)`,
        `![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)`,
        `![ERP](https://img.shields.io/badge/ERP-${encodeURIComponent(erpSystem)}-orange.svg)`,
        `![License](https://img.shields.io/badge/license-Proprietary-red.svg)`,
        `![Generated](https://img.shields.io/badge/generated_by-Agentics_Pipeline-blueviolet.svg)`,
        '',
        '---',
        '',
        '## Overview',
        '',
        `**${serviceNameUpper}** is an enterprise-grade service generated by the Agentics CLI pipeline. ` +
            `It provides a production-ready TypeScript application with full ERP integration, ` +
            `domain-driven design architecture, and comprehensive test coverage.`,
        '',
        `This service integrates with **${erpSystem}** and follows SPARC methodology with London School TDD practices.`,
        '',
        '---',
        '',
        '## Architecture',
        '',
        '```',
        '┌─────────────┐    ┌─────────────┐    ┌─────────────┐',
        '│   HTTP API   │───>│   Domain    │───>│  ERP Layer  │',
        '│  (Hono.js)  │    │  (Commands  │    │  (Adapter)  │',
        '│             │    │   Queries)  │    │             │',
        '└─────────────┘    └─────────────┘    └─────────────┘',
        '       │                  │                  │',
        '       v                  v                  v',
        '  Validation         Events &           External',
        '  Middleware          Aggregates        ERP System',
        '```',
        '',
        '### Domain-Driven Design Structure',
        '',
        '```',
        'src/',
        '├── contexts/              # Bounded contexts (DDD)',
        '│   └── <context>/',
        '│       ├── domain/',
        '│       │   ├── commands/  # Command handlers',
        '│       │   ├── queries/   # Query handlers',
        '│       │   ├── events/    # Domain events',
        '│       │   └── aggregates/ # Aggregate roots',
        '│       └── ports/         # Port interfaces (seams)',
        '├── server/',
        '│   ├── main.ts            # Application entrypoint',
        '│   └── routes.ts          # HTTP route handlers',
        '├── middleware/',
        '│   ├── validation.ts      # Zod schema validation',
        '│   └── health.ts          # Health check endpoint',
        '├── integrations/',
        '│   ├── erp-client.ts      # ERP API client',
        '│   └── event-mapping.ts   # Domain-to-ERP event mapping',
        '└── di/',
        '    └── factory.ts         # Dependency injection',
        '```',
        '',
        '---',
        '',
        '## Quick Start',
        '',
        '### Prerequisites',
        '',
        '- Node.js >= 18.0.0',
        '- npm >= 9.0.0',
        '',
        '### Installation',
        '',
        '```bash',
        'npm install',
        '```',
        '',
        '### Development',
        '',
        '```bash',
        '# Run tests',
        'npm test',
        '',
        '# Build',
        'npm run build',
        '',
        '# Start locally',
        'npm start',
        '```',
        '',
        '---',
        '',
        '## API Endpoints',
        '',
        '| Method | Path | Description |',
        '|--------|------|-------------|',
        '| GET | `/health` | Health check and readiness probe |',
        ...(endpoints.length > 0
            ? endpoints.map(ep => `| POST | \`${ep}\` | Domain command/query endpoint |`)
            : [
                '| POST | `/api/commands/:command` | Execute domain command |',
                '| GET | `/api/queries/:query` | Execute domain query |',
            ]),
        '',
        '---',
        '',
        '## ERP Integration',
        '',
        `| Property | Value |`,
        `|----------|-------|`,
        `| ERP System | ${erpSystem} |`,
        `| Auth Scheme | ${vars.erpAuthScheme} |`,
        `| VPC Connector | ${vars.vpcConnector} |`,
        `| Region | ${vars.region} |`,
        '',
        '### Environment Variables',
        '',
        '| Variable | Description | Required |',
        '|----------|-------------|----------|',
        '| `PORT` | Server port (default: 8080) | No |',
        '| `NODE_ENV` | Environment (production/development) | Yes |',
        `| \`ERP_SYSTEM\` | ERP system identifier (${erpSystem}) | Yes |`,
        ...vars.erpEnvVars.map(v => `| \`${v}\` | ERP connection variable | Yes |`),
        '',
        '---',
        '',
        '## Deployment',
        '',
        '### Docker',
        '',
        '```bash',
        'docker build -t ' + serviceName + ' .',
        'docker run -p 8080:8080 --env-file .env ' + serviceName,
        '```',
        '',
        '### Kubernetes',
        '',
        '```bash',
        'kubectl apply -f deployment/k8s/',
        '```',
        '',
        '### Cloud Run (GCP)',
        '',
        '```bash',
        'chmod +x deploy/deploy.sh',
        'GCP_PROJECT_ID=your-project ./deploy/deploy.sh',
        '```',
        '',
        '---',
        '',
        '## Testing',
        '',
        'This project uses **Vitest** with London School TDD (mockist) patterns.',
        '',
        '```bash',
        '# Run all tests',
        'npm test',
        '',
        '# Run with coverage',
        'npm run test:coverage',
        '',
        '# Run specific test suite',
        'npx vitest run tests/unit/',
        '```',
        '',
        '### Test Structure',
        '',
        '- `tests/unit/` — Unit tests per bounded context (mock at aggregate boundaries)',
        '- `tests/integration/` — Seam integration tests (adapter contract verification)',
        '- `tests/mocks/` — Shared mock factories',
        '',
        '---',
        '',
        '## Security',
        '',
        '- All inputs validated via Zod schemas at the middleware layer',
        '- Non-root container execution',
        '- VPC-isolated ERP network access',
        '- Secret Manager integration for API keys and credentials',
        '- Health check endpoint excludes sensitive data',
        '',
        '---',
        '',
        '## Generated By',
        '',
        'This project was generated by the **Agentics CLI** enterprise pipeline.',
        '',
        '| Artifact | Source |',
        '|----------|--------|',
        '| Architecture | SPARC Specification (Phase 3) |',
        '| Domain Model | DDD Bounded Contexts (Phase 4) |',
        '| Test Plan | London School TDD (Phase 3) |',
        '| Deployment | ERP Surface Push (Phase 6) |',
        '',
        '> For pipeline documentation, see `.agentics/plans/`',
        '',
        '---',
        '',
        `*Generated on ${new Date().toISOString().split('T')[0]} by [Agentics CLI](https://platform.agentics.dev)*`,
        '',
    ].join('\n');
}
// ============================================================================
// Main: finalizeDeployment
// ============================================================================
/**
 * Stage 4: Generate production-ready deployment scripts.
 *
 * @param context - The mutable Phase 6 pipeline context
 * @returns Stage output describing success or failure
 */
export function finalizeDeployment(context) {
    const startTime = Date.now();
    const rootSpan = createSpan('deployment-finalization', 'finalize-deployment', {
        phase6Dir: context.phase6Dir,
        erpSystem: context.phase5Artifacts.erpSystem,
    });
    try {
        const vars = deriveDeploymentVars(context);
        const erpSystem = context.phase5Artifacts.erpSystem;
        const infraRepoPath = resolveInfraRepoPath(context.platformRepoPaths);
        const varsSpan = createSpan('deployment-finalization', 'derive-vars', {}, rootSpan.spanId);
        const finalVarsSpan = endSpan(varsSpan, 'ok', {
            serviceName: vars.serviceName, hasInfraRepo: infraRepoPath !== undefined,
        });
        emitSpan(finalVarsSpan);
        context.telemetrySpans.push(finalVarsSpan);
        const deployDir = join(context.phase6Dir, 'deploy');
        mkdirSync(deployDir, { recursive: true, mode: DIR_MODE });
        const writtenPaths = [];
        const genSpan = createSpan('deployment-finalization', 'generate-scripts', { deployDir }, rootSpan.spanId);
        writeScript(join(deployDir, 'deploy.sh'), generateDeployScript(vars, erpSystem));
        writtenPaths.push(join(deployDir, 'deploy.sh'));
        writeScript(join(deployDir, 'teardown.sh'), generateTeardownScript(vars));
        writtenPaths.push(join(deployDir, 'teardown.sh'));
        writeArtifact(join(deployDir, 'env.template'), generateEnvTemplate(vars, erpSystem));
        writtenPaths.push(join(deployDir, 'env.template'));
        writeScript(join(deployDir, 'vpc-setup.sh'), generateVpcSetupScript(vars, infraRepoPath));
        writtenPaths.push(join(deployDir, 'vpc-setup.sh'));
        writeArtifact(join(deployDir, 'monitoring.yaml'), generateMonitoringYaml(vars));
        writtenPaths.push(join(deployDir, 'monitoring.yaml'));
        // Generate enterprise README.md for the project root
        const projectDir = join(context.phase6Dir, 'project');
        if (existsSync(projectDir)) {
            const readmeContent = generateReadme(vars, erpSystem, context);
            writeArtifact(join(projectDir, 'README.md'), readmeContent);
            writtenPaths.push(join(projectDir, 'README.md'));
        }
        const finalGenSpan = endSpan(genSpan, 'ok', { filesGenerated: writtenPaths.length });
        emitSpan(finalGenSpan);
        context.telemetrySpans.push(finalGenSpan);
        const finalRootSpan = endSpan(rootSpan, 'ok', {
            serviceName: vars.serviceName, erpSystem, filesGenerated: writtenPaths.length,
        });
        emitSpan(finalRootSpan);
        context.telemetrySpans.push(finalRootSpan);
        const timing = Date.now() - startTime;
        const output = {
            stage: 'deployment-finalization',
            status: 'completed',
            data: {
                deployDir, serviceName: vars.serviceName, region: vars.region,
                vpcConnector: vars.vpcConnector, filesGenerated: writtenPaths.length,
            },
            artifacts: writtenPaths,
            timing,
        };
        context.stageOutputs.set('deployment-finalization', output);
        return output;
    }
    catch (err) {
        const errorMessage = err instanceof Error ? err.message : String(err);
        const finalRootSpan = endSpan(rootSpan, 'error', { error: errorMessage });
        emitSpan(finalRootSpan);
        context.telemetrySpans.push(finalRootSpan);
        const timing = Date.now() - startTime;
        const output = {
            stage: 'deployment-finalization',
            status: 'failed',
            data: { error: errorMessage },
            artifacts: [],
            timing,
        };
        context.stageOutputs.set('deployment-finalization', output);
        return output;
    }
}
//# sourceMappingURL=deployment-finalizer.js.map