/**
 * Phase 4 Pipeline -- Stage 7: Deployment Generator
 *
 * Generates cloud-provider-specific deployment descriptors based on the
 * cloudProvider field in ERPResolution:
 *
 *   gcp (default)  -- Cloud Run: Knative YAML, Cloud Build, GCP .env.example
 *   aws            -- ECS/Fargate: task-definition.json, buildspec.yml, AWS .env.example
 *   azure          -- Container Apps: container-app.yaml, azure-pipelines.yml, Azure .env.example
 *   alibaba/on-prem -- Dockerfile + generic .env.example (no orchestrator-specific files)
 *
 * The Dockerfile is cloud-agnostic and shared across all providers.
 *
 * TypeScript target: Node 20 multi-stage Docker build.
 * Rust target: Rust 1.77 / Debian bookworm-slim multi-stage Docker build.
 *
 * All generated files carry a "do not edit manually" header.
 *
 * Exports:
 *   - generateDeployment(context) -- pipeline entry point
 *
 * Error codes:
 *   ECLI-P4-070  Missing prerequisite stage output (erp-target-resolution)
 *   ECLI-P4-071  Deployment file write failure
 */
import { mkdirSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { hasTemplateSupport } from '../types.js';
import { createSpan, endSpan, emitSpan } from '../../phase2/telemetry.js';
// ============================================================================
// Constants
// ============================================================================
const DIR_MODE = 0o700;
const FILE_MODE = 0o600;
// ============================================================================
// Dockerfile Generation (cloud-agnostic)
// ============================================================================
/**
 * Generate a multi-stage Dockerfile for a TypeScript / Node 20 service.
 * Cloud-agnostic -- works on any container runtime.
 */
function tsDockerfile() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '',
        '# Stage 1: build',
        'FROM node:20-slim AS builder',
        'WORKDIR /app',
        'COPY package*.json ./',
        'RUN npm ci',
        'COPY . .',
        'RUN npm run build',
        '',
        '# Stage 2: runtime',
        'FROM node:20-slim',
        'WORKDIR /app',
        'ENV NODE_ENV=production',
        'COPY --from=builder /app/dist ./dist',
        'COPY --from=builder /app/node_modules ./node_modules',
        'EXPOSE 8080',
        'USER node',
        'CMD ["node", "dist/server/main.js"]',
        '',
    ].join('\n');
}
/**
 * Generate a multi-stage Dockerfile for a Rust / Axum service.
 * Cloud-agnostic -- works on any container runtime.
 */
function rustDockerfile() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '',
        '# Stage 1: build',
        'FROM rust:1.77 AS builder',
        'WORKDIR /app',
        'COPY Cargo.toml Cargo.lock ./',
        'COPY src ./src',
        'RUN cargo build --release',
        '',
        '# Stage 2: runtime (minimal debian image)',
        'FROM debian:bookworm-slim',
        'RUN apt-get update && apt-get install -y --no-install-recommends \\',
        '    ca-certificates \\',
        '    && rm -rf /var/lib/apt/lists/*',
        'RUN groupadd -r appuser && useradd -r -g appuser appuser',
        'COPY --from=builder /app/target/release/server /usr/local/bin/server',
        'EXPOSE 8080',
        'USER appuser',
        'CMD ["server"]',
        '',
    ].join('\n');
}
// ============================================================================
// GCP: Cloud Run + Cloud Build
// ============================================================================
/**
 * Generate a Knative Serving manifest for Cloud Run.
 */
function cloudRunServiceYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'apiVersion: serving.knative.dev/v1',
        'kind: Service',
        'metadata:',
        `  name: mvp-${traceIdShort}`,
        '  annotations:',
        '    run.googleapis.com/ingress: internal-and-cloud-load-balancing',
        'spec:',
        '  template:',
        '    metadata:',
        '      annotations:',
        '        autoscaling.knative.dev/minScale: "0"',
        '        autoscaling.knative.dev/maxScale: "10"',
        '        run.googleapis.com/cpu-throttling: "false"',
        '    spec:',
        '      serviceAccountName: mvp-service@PROJECT_ID.iam.gserviceaccount.com',
        '      containerConcurrency: 80',
        '      containers:',
        '        - image: IMAGE_URL',
        '          ports:',
        '            - containerPort: 8080',
        '          env:',
        '            - name: PORT',
        '              value: "8080"',
        '            - name: DB_CONNECTION_STRING',
        '              value: "" # Set via Secret Manager',
        '            - name: ERP_SURFACE_URL',
        '              value: "" # Set during deployment',
        '          resources:',
        '            limits:',
        '              cpu: "1"',
        '              memory: 512Mi',
        '',
    ].join('\n');
}
/**
 * Generate a Cloud Build pipeline YAML.
 */
function cloudBuildYaml() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'steps:',
        '  - name: gcr.io/cloud-builders/docker',
        '    args:',
        "      - 'build'",
        "      - '-t'",
        "      - 'IMAGE_URL'",
        "      - '.'",
        '',
        '  - name: gcr.io/cloud-builders/docker',
        '    args:',
        "      - 'push'",
        "      - 'IMAGE_URL'",
        '',
        '  - name: gcr.io/google.com/cloudsdktool/cloud-sdk',
        '    entrypoint: gcloud',
        '    args:',
        "      - 'run'",
        "      - 'deploy'",
        "      - 'SERVICE_NAME'",
        "      - '--image'",
        "      - 'IMAGE_URL'",
        "      - '--region'",
        "      - 'us-central1'",
        "      - '--platform'",
        "      - 'managed'",
        "      - '--quiet'",
        '',
        'images:',
        "  - 'IMAGE_URL'",
        '',
    ].join('\n');
}
/**
 * Generate a GCP-specific .env.example.
 */
function gcpEnvExample() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '# Copy this file to .env and fill in values before running locally.',
        '# Never commit .env to version control.',
        '',
        'PORT=8080',
        'DB_CONNECTION_STRING=',
        'ERP_SURFACE_URL=',
        'GCP_PROJECT_ID=',
        'SERVICE_ACCOUNT_EMAIL=',
        'OTEL_EXPORTER_OTLP_ENDPOINT=',
        'LOG_LEVEL=info',
        '',
    ].join('\n');
}
// ============================================================================
// AWS: ECS/Fargate + CodeBuild
// ============================================================================
/**
 * Generate an ECS Fargate task definition JSON.
 */
function ecsTaskDefinitionJson(traceIdShort) {
    const taskDef = {
        family: `mvp-${traceIdShort}`,
        networkMode: 'awsvpc',
        requiresCompatibilities: ['FARGATE'],
        cpu: '256',
        memory: '512',
        executionRoleArn: 'arn:aws:iam::ACCOUNT_ID:role/ecsTaskExecutionRole',
        taskRoleArn: 'arn:aws:iam::ACCOUNT_ID:role/ecsTaskRole',
        containerDefinitions: [
            {
                name: `mvp-${traceIdShort}`,
                image: 'IMAGE_URL',
                essential: true,
                portMappings: [
                    {
                        containerPort: 8080,
                        protocol: 'tcp',
                    },
                ],
                environment: [
                    { name: 'PORT', value: '8080' },
                    { name: 'DB_CONNECTION_STRING', value: '' },
                    { name: 'ERP_SURFACE_URL', value: '' },
                ],
                logConfiguration: {
                    logDriver: 'awslogs',
                    options: {
                        'awslogs-group': `/ecs/mvp-${traceIdShort}`,
                        'awslogs-region': 'us-east-1',
                        'awslogs-stream-prefix': 'ecs',
                    },
                },
                healthCheck: {
                    command: ['CMD-SHELL', 'curl -f http://localhost:8080/health || exit 1'],
                    interval: 30,
                    timeout: 5,
                    retries: 3,
                    startPeriod: 60,
                },
            },
        ],
    };
    return [
        '// Generated by Phase 4 pipeline — do not edit manually',
        JSON.stringify(taskDef, null, 2),
        '',
    ].join('\n');
}
/**
 * Generate an AWS CodeBuild buildspec.yml.
 */
function awsBuildspecYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'version: 0.2',
        '',
        'phases:',
        '  pre_build:',
        '    commands:',
        '      - echo Logging in to Amazon ECR...',
        '      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com',
        '  build:',
        '    commands:',
        '      - echo Building Docker image...',
        '      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .',
        '      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG',
        '  post_build:',
        '    commands:',
        '      - echo Pushing Docker image...',
        '      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG',
        `      - printf '[{"name":"mvp-${traceIdShort}","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json`,
        '',
        'artifacts:',
        '  files:',
        '    - imagedefinitions.json',
        '',
    ].join('\n');
}
/**
 * Generate an AWS-specific .env.example.
 */
function awsEnvExample() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '# Copy this file to .env and fill in values before running locally.',
        '# Never commit .env to version control.',
        '',
        'PORT=8080',
        'DB_CONNECTION_STRING=',
        'ERP_SURFACE_URL=',
        'AWS_REGION=us-east-1',
        'AWS_ACCOUNT_ID=',
        'ECS_CLUSTER_NAME=',
        'ECS_SERVICE_NAME=',
        'OTEL_EXPORTER_OTLP_ENDPOINT=',
        'LOG_LEVEL=info',
        '',
    ].join('\n');
}
// ============================================================================
// Azure: Container Apps + Azure DevOps
// ============================================================================
/**
 * Generate an Azure Container Apps YAML manifest.
 */
function azureContainerAppYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'apiVersion: 2023-05-01',
        'type: Microsoft.App/containerApps',
        `name: mvp-${traceIdShort}`,
        'location: eastus',
        'properties:',
        '  managedEnvironmentId: /subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP/providers/Microsoft.App/managedEnvironments/ENVIRONMENT_NAME',
        '  configuration:',
        '    ingress:',
        '      external: true',
        '      targetPort: 8080',
        '      transport: http',
        '    secrets:',
        '      - name: db-connection-string',
        '        value: "" # Set via Azure Key Vault reference',
        '  template:',
        '    containers:',
        `      - name: mvp-${traceIdShort}`,
        '        image: IMAGE_URL',
        '        resources:',
        '          cpu: 0.5',
        '          memory: 1Gi',
        '        env:',
        '          - name: PORT',
        '            value: "8080"',
        '          - name: DB_CONNECTION_STRING',
        '            secretRef: db-connection-string',
        '          - name: ERP_SURFACE_URL',
        '            value: "" # Set during deployment',
        '    scale:',
        '      minReplicas: 0',
        '      maxReplicas: 10',
        '      rules:',
        '        - name: http-scaling',
        '          http:',
        '            metadata:',
        '              concurrentRequests: "80"',
        '',
    ].join('\n');
}
/**
 * Generate an Azure DevOps pipeline YAML.
 */
function azurePipelinesYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'trigger:',
        '  branches:',
        '    include:',
        '      - main',
        '',
        'pool:',
        '  vmImage: ubuntu-latest',
        '',
        'variables:',
        '  containerRegistry: REGISTRY_NAME.azurecr.io',
        `  imageName: mvp-${traceIdShort}`,
        '  tag: $(Build.BuildId)',
        '',
        'stages:',
        '  - stage: Build',
        '    displayName: Build and push image',
        '    jobs:',
        '      - job: Build',
        '        steps:',
        '          - task: Docker@2',
        '            displayName: Build and push',
        '            inputs:',
        '              containerRegistry: $(containerRegistry)',
        '              repository: $(imageName)',
        '              command: buildAndPush',
        '              Dockerfile: "**/Dockerfile"',
        '              tags: |',
        '                $(tag)',
        '                latest',
        '',
        '  - stage: Deploy',
        '    displayName: Deploy to Container Apps',
        '    dependsOn: Build',
        '    jobs:',
        '      - job: Deploy',
        '        steps:',
        '          - task: AzureCLI@2',
        '            displayName: Deploy Container App',
        '            inputs:',
        '              azureSubscription: AZURE_SUBSCRIPTION',
        '              scriptType: bash',
        '              scriptLocation: inlineScript',
        '              inlineScript: |',
        `                az containerapp update \\`,
        `                  --name mvp-${traceIdShort} \\`,
        '                  --resource-group $(resourceGroup) \\',
        '                  --image $(containerRegistry)/$(imageName):$(tag)',
        '',
    ].join('\n');
}
/**
 * Generate an Azure-specific .env.example.
 */
function azureEnvExample() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '# Copy this file to .env and fill in values before running locally.',
        '# Never commit .env to version control.',
        '',
        'PORT=8080',
        'DB_CONNECTION_STRING=',
        'ERP_SURFACE_URL=',
        'AZURE_SUBSCRIPTION_ID=',
        'AZURE_RESOURCE_GROUP=',
        'AZURE_CONTAINER_REGISTRY=',
        'OTEL_EXPORTER_OTLP_ENDPOINT=',
        'LOG_LEVEL=info',
        '',
    ].join('\n');
}
// ============================================================================
// Kubernetes Manifests (generated for all providers)
// ============================================================================
function k8sDeploymentYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'apiVersion: apps/v1',
        'kind: Deployment',
        'metadata:',
        `  name: mvp-${traceIdShort}`,
        '  labels:',
        `    app: mvp-${traceIdShort}`,
        'spec:',
        '  replicas: 3',
        '  selector:',
        '    matchLabels:',
        `      app: mvp-${traceIdShort}`,
        '  strategy:',
        '    type: RollingUpdate',
        '    rollingUpdate:',
        '      maxSurge: 1',
        '      maxUnavailable: 0',
        '  template:',
        '    metadata:',
        '      labels:',
        `        app: mvp-${traceIdShort}`,
        '    spec:',
        '      containers:',
        `        - name: mvp-${traceIdShort}`,
        '          image: IMAGE_URL',
        '          ports:',
        '            - containerPort: 8080',
        '              protocol: TCP',
        '          env:',
        '            - name: PORT',
        '              value: "8080"',
        '            - name: NODE_ENV',
        '              value: production',
        '            - name: ERP_SURFACE_URL',
        '              valueFrom:',
        '                configMapKeyRef:',
        `                  name: mvp-${traceIdShort}-config`,
        '                  key: ERP_SURFACE_URL',
        '          resources:',
        '            requests:',
        '              cpu: 250m',
        '              memory: 128Mi',
        '            limits:',
        '              cpu: 500m',
        '              memory: 256Mi',
        '          livenessProbe:',
        '            httpGet:',
        '              path: /health',
        '              port: 8080',
        '            initialDelaySeconds: 15',
        '            periodSeconds: 20',
        '          readinessProbe:',
        '            httpGet:',
        '              path: /health',
        '              port: 8080',
        '            initialDelaySeconds: 5',
        '            periodSeconds: 10',
        '      securityContext:',
        '        runAsNonRoot: true',
        '        runAsUser: 1000',
        '',
    ].join('\n');
}
function k8sServiceYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'apiVersion: v1',
        'kind: Service',
        'metadata:',
        `  name: mvp-${traceIdShort}`,
        '  labels:',
        `    app: mvp-${traceIdShort}`,
        'spec:',
        '  type: ClusterIP',
        '  ports:',
        '    - port: 80',
        '      targetPort: 8080',
        '      protocol: TCP',
        '  selector:',
        `    app: mvp-${traceIdShort}`,
        '',
    ].join('\n');
}
function k8sConfigMapYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '# Update values before deploying to your cluster.',
        'apiVersion: v1',
        'kind: ConfigMap',
        'metadata:',
        `  name: mvp-${traceIdShort}-config`,
        'data:',
        '  ERP_SURFACE_URL: ""',
        '  LOG_LEVEL: info',
        '  NODE_ENV: production',
        '',
    ].join('\n');
}
function k8sHpaYaml(traceIdShort) {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        'apiVersion: autoscaling/v2',
        'kind: HorizontalPodAutoscaler',
        'metadata:',
        `  name: mvp-${traceIdShort}`,
        'spec:',
        '  scaleTargetRef:',
        '    apiVersion: apps/v1',
        '    kind: Deployment',
        `    name: mvp-${traceIdShort}`,
        '  minReplicas: 3',
        '  maxReplicas: 12',
        '  metrics:',
        '    - type: Resource',
        '      resource:',
        '        name: cpu',
        '        target:',
        '          type: Utilization',
        '          averageUtilization: 70',
        '',
    ].join('\n');
}
// ============================================================================
// Generic .env.example (alibaba, on-prem)
// ============================================================================
/**
 * Generate a generic .env.example for providers without specialized templates.
 */
function genericEnvExample() {
    return [
        '# Generated by Phase 4 pipeline — do not edit manually',
        '# Copy this file to .env and fill in values before running locally.',
        '# Never commit .env to version control.',
        '',
        'PORT=8080',
        'DB_CONNECTION_STRING=',
        'ERP_SURFACE_URL=',
        'CONTAINER_REGISTRY=',
        'OTEL_EXPORTER_OTLP_ENDPOINT=',
        'LOG_LEVEL=info',
        '',
    ].join('\n');
}
// ============================================================================
// File Writing
// ============================================================================
/**
 * Write a deployment file to disk, creating parent directories as needed.
 */
function writeDeploymentFile(absPath, content) {
    const dir = absPath.substring(0, absPath.lastIndexOf('/'));
    mkdirSync(dir, { recursive: true, mode: DIR_MODE });
    try {
        writeFileSync(absPath, content, { encoding: 'utf-8', mode: FILE_MODE });
    }
    catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        throw new Error(`ECLI-P4-071: Failed to write deployment file ${absPath}: ${message}`);
    }
}
// ============================================================================
// Provider-Specific File Generators
// ============================================================================
/**
 * Generate GCP Cloud Run deployment files.
 */
function generateGcpFiles(_deployDir, traceIdShort) {
    return [
        { relativePath: 'deployment/cloud-run-service.yaml', content: cloudRunServiceYaml(traceIdShort) },
        { relativePath: 'deployment/cloudbuild.yaml', content: cloudBuildYaml() },
        { relativePath: 'deployment/.env.example', content: gcpEnvExample() },
    ];
}
/**
 * Generate AWS ECS/Fargate deployment files.
 */
function generateAwsFiles(_deployDir, traceIdShort) {
    return [
        { relativePath: 'deployment/task-definition.json', content: ecsTaskDefinitionJson(traceIdShort) },
        { relativePath: 'deployment/buildspec.yml', content: awsBuildspecYaml(traceIdShort) },
        { relativePath: 'deployment/.env.example', content: awsEnvExample() },
    ];
}
/**
 * Generate Azure Container Apps deployment files.
 */
function generateAzureFiles(_deployDir, traceIdShort) {
    return [
        { relativePath: 'deployment/container-app.yaml', content: azureContainerAppYaml(traceIdShort) },
        { relativePath: 'deployment/azure-pipelines.yml', content: azurePipelinesYaml(traceIdShort) },
        { relativePath: 'deployment/.env.example', content: azureEnvExample() },
    ];
}
/**
 * Generate generic deployment files (alibaba, on-prem).
 */
function generateGenericFiles(_deployDir, _traceIdShort) {
    return [
        { relativePath: 'deployment/.env.example', content: genericEnvExample() },
    ];
}
/**
 * Generate Kubernetes deployment manifests (universal, all providers).
 */
function generateK8sFiles(_deployDir, traceIdShort) {
    return [
        { relativePath: 'deployment/k8s/deployment.yaml', content: k8sDeploymentYaml(traceIdShort) },
        { relativePath: 'deployment/k8s/service.yaml', content: k8sServiceYaml(traceIdShort) },
        { relativePath: 'deployment/k8s/configmap.yaml', content: k8sConfigMapYaml(traceIdShort) },
        { relativePath: 'deployment/k8s/hpa.yaml', content: k8sHpaYaml(traceIdShort) },
    ];
}
// ============================================================================
// Public: Pipeline Entry Point
// ============================================================================
/**
 * Stage 7 entry point: generate cloud-provider-specific deployment descriptors.
 *
 * Reads ERPResolution from context.stageOutputs.get('erp-target-resolution'),
 * checks cloudProvider to determine which deployment templates to generate,
 * derives a short trace ID suffix, and writes all deployment files to
 * phase4/deployment/.
 *
 * Supported providers:
 *   - gcp (default): Cloud Run + Cloud Build
 *   - aws: ECS/Fargate + CodeBuild
 *   - azure: Container Apps + Azure DevOps Pipelines
 *   - alibaba, on-prem: Dockerfile + generic .env.example
 *
 * @param context - The Phase 4 pipeline context
 * @returns Stage output describing success or failure
 */
export function generateDeployment(context) {
    const startTime = Date.now();
    const rootSpan = createSpan('deployment-generation', 'generate-deployment', {
        phase4Dir: context.phase4Dir,
        traceId: context.traceId,
    });
    try {
        // Verify ERP target resolution completed
        const erpStage = context.stageOutputs.get('erp-target-resolution');
        if (!erpStage || erpStage.status !== 'completed') {
            throw new Error('ECLI-P4-070: ERP target resolution not available on context. ' +
                'Ensure the erp-target-resolution stage completed successfully before running deployment-generation.');
        }
        const erpResolution = erpStage.data;
        const cloudProvider = erpResolution.cloudProvider ?? 'gcp';
        // Resolve implementation language and short trace ID
        const language = context.phase3Artifacts.implementationLanguage;
        // Non-TS/Rust languages handled by Ruflo swarm
        if (!hasTemplateSupport(language)) {
            const span = endSpan(rootSpan, 'ok', { delegated: true, language });
            emitSpan(span);
            return {
                stage: 'deployment-generation',
                status: 'completed',
                data: { files: [], cloudRunService: 'delegated-to-ruflo' },
                artifacts: [],
                timing: Date.now() - startTime,
                summary: `Deployment for ${language} delegated to Ruflo swarm.`,
            };
        }
        const traceIdShort = context.traceId.slice(0, 8);
        const isTs = language === 'typescript';
        // Output directory: phase4/deployment/
        const deployDir = join(context.phase4Dir, 'deployment');
        mkdirSync(deployDir, { recursive: true, mode: DIR_MODE });
        const deployFiles = [];
        const writtenPaths = [];
        const genSpan = createSpan('deployment-generation', 'generate-files', { language, traceIdShort, cloudProvider }, rootSpan.spanId);
        // Dockerfile (language-specific, cloud-agnostic)
        const dockerfileContent = isTs ? tsDockerfile() : rustDockerfile();
        const dockerfilePath = join(deployDir, 'Dockerfile');
        writeDeploymentFile(dockerfilePath, dockerfileContent);
        deployFiles.push({ relativePath: 'deployment/Dockerfile', content: dockerfileContent, kind: 'deployment' });
        writtenPaths.push(dockerfilePath);
        // Provider-specific deployment files
        let providerFiles;
        switch (cloudProvider) {
            case 'aws':
                providerFiles = generateAwsFiles(deployDir, traceIdShort);
                break;
            case 'azure':
                providerFiles = generateAzureFiles(deployDir, traceIdShort);
                break;
            case 'alibaba':
            case 'on-prem':
                providerFiles = generateGenericFiles(deployDir, traceIdShort);
                break;
            case 'gcp':
            default:
                providerFiles = generateGcpFiles(deployDir, traceIdShort);
                break;
        }
        // Kubernetes manifests — generated for all providers (K8s is universal)
        const k8sFiles = generateK8sFiles(deployDir, traceIdShort);
        for (const kf of k8sFiles) {
            const fileName = kf.relativePath.replace('deployment/', '');
            const absPath = join(deployDir, fileName);
            writeDeploymentFile(absPath, kf.content);
            deployFiles.push({ relativePath: kf.relativePath, content: kf.content, kind: 'deployment' });
            writtenPaths.push(absPath);
        }
        for (const pf of providerFiles) {
            const fileName = pf.relativePath.replace('deployment/', '');
            const absPath = join(deployDir, fileName);
            writeDeploymentFile(absPath, pf.content);
            deployFiles.push({ relativePath: pf.relativePath, content: pf.content, kind: 'deployment' });
            writtenPaths.push(absPath);
        }
        const serviceName = `mvp-${traceIdShort}`;
        // ADR-063: Copy essential deployment files into project/ so they travel with the code
        const projectDir = join(context.phase4Dir, 'project');
        try {
            mkdirSync(projectDir, { recursive: true, mode: DIR_MODE });
            // Dockerfile at project root
            const projectDockerfilePath = join(projectDir, 'Dockerfile');
            // Check if Rust optimizer exists — generate multi-stage Dockerfile
            const hasRustOptimizer = /\brust\b/i.test(context.scenarioQuery) &&
                /graph|optim|simul|network|dependency|pareto|compute/i.test(context.scenarioQuery);
            const finalDockerfile = hasRustOptimizer ? [
                '# Generated by Phase 4 pipeline — do not edit manually',
                '',
                '# Stage 1: Build Rust optimizer engine',
                'FROM rust:1.77-slim AS rust-builder',
                'WORKDIR /app/optimizer-engine',
                'COPY optimizer-engine/ .',
                'RUN cargo build --release',
                '',
                '# Stage 2: Build TypeScript',
                'FROM node:20-slim AS ts-builder',
                'WORKDIR /app',
                'COPY package*.json ./',
                'RUN npm ci',
                'COPY tsconfig.json ./',
                'COPY src/ src/',
                'RUN npm run build',
                '',
                '# Stage 3: Production runtime',
                'FROM node:20-slim',
                'WORKDIR /app',
                'ENV NODE_ENV=production',
                'COPY --from=ts-builder /app/dist ./dist',
                'COPY --from=ts-builder /app/node_modules ./node_modules',
                'COPY --from=rust-builder /app/optimizer-engine/target/release/*-optimizer ./optimizer-engine/target/release/',
                'COPY package.json ./',
                'EXPOSE 8080',
                'USER node',
                'CMD ["node", "dist/server/main.js"]',
                '',
            ].join('\n') : dockerfileContent;
            writeFileSync(projectDockerfilePath, finalDockerfile, { encoding: 'utf-8', mode: FILE_MODE });
            writtenPaths.push(projectDockerfilePath);
            // .env.example at project root
            for (const pf of providerFiles) {
                if (pf.relativePath.includes('.env')) {
                    writeFileSync(join(projectDir, '.env.example'), pf.content, { encoding: 'utf-8', mode: FILE_MODE });
                    writtenPaths.push(join(projectDir, '.env.example'));
                    break;
                }
            }
            // Cloud Run service.yaml / task-definition.json at project root
            for (const pf of providerFiles) {
                if (pf.relativePath.includes('service.yaml') || pf.relativePath.includes('task-definition')) {
                    const fileName = pf.relativePath.split('/').pop();
                    writeFileSync(join(projectDir, fileName), pf.content, { encoding: 'utf-8', mode: FILE_MODE });
                    writtenPaths.push(join(projectDir, fileName));
                    break;
                }
            }
            // Makefile
            const makefileContent = [
                '# Generated by Phase 4 pipeline — do not edit manually',
                '.PHONY: build test dev docker deploy clean',
                '',
                'build:',
                '\tnpm run build',
                hasRustOptimizer ? '\tcd optimizer-engine && cargo build --release' : '',
                '',
                'test:',
                '\tnpm test',
                hasRustOptimizer ? '\tcd optimizer-engine && cargo test' : '',
                '',
                'dev:',
                '\tnpm run dev',
                '',
                'docker:',
                `\tdocker build -t ${serviceName} .`,
                '',
                'deploy:',
                `\tgcloud run deploy ${serviceName} --image gcr.io/$$(gcloud config get-value project)/${serviceName} --region us-central1`,
                '',
                'clean:',
                '\trm -rf dist',
                hasRustOptimizer ? '\tcd optimizer-engine && cargo clean' : '',
                '',
            ].filter(Boolean).join('\n');
            writeFileSync(join(projectDir, 'Makefile'), makefileContent, { encoding: 'utf-8', mode: FILE_MODE });
            writtenPaths.push(join(projectDir, 'Makefile'));
        }
        catch (err) {
            // Non-fatal — deployment files in deployment/ dir still exist
            console.error(`[deployment] ADR-063: Could not copy to project/: ${err instanceof Error ? err.message : String(err)}`);
        }
        const finalGenSpan = endSpan(genSpan, 'ok', { filesGenerated: writtenPaths.length, cloudRunService: serviceName });
        emitSpan(finalGenSpan);
        const finalRootSpan = endSpan(rootSpan, 'ok', {
            language,
            traceIdShort,
            cloudProvider,
            filesGenerated: writtenPaths.length,
            cloudRunService: serviceName,
        });
        emitSpan(finalRootSpan);
        const providerLabel = {
            gcp: 'Cloud Run',
            aws: 'ECS/Fargate',
            azure: 'Container Apps',
            alibaba: 'Alibaba Cloud',
            'on-prem': 'on-prem',
        };
        const timing = Date.now() - startTime;
        const fileNames = deployFiles.map((f) => f.relativePath.replace('deployment/', '')).join(', ');
        const output = {
            stage: 'deployment-generation',
            status: 'completed',
            data: {
                files: deployFiles,
                cloudRunService: serviceName,
            },
            artifacts: writtenPaths,
            timing,
            summary: `Generated deployment descriptors (${language}, ${providerLabel[cloudProvider]}): ` +
                `${fileNames} ` +
                `for service "${serviceName}" ` +
                `(${writtenPaths.length} files in ${timing}ms)`,
        };
        context.stageOutputs.set('deployment-generation', output);
        return output;
    }
    catch (err) {
        const errorMessage = err instanceof Error ? err.message : String(err);
        const finalRootSpan = endSpan(rootSpan, 'error', { error: errorMessage });
        emitSpan(finalRootSpan);
        const timing = Date.now() - startTime;
        const output = {
            stage: 'deployment-generation',
            status: 'failed',
            data: { error: errorMessage },
            artifacts: [],
            timing,
            summary: `Deployment generation failed: ${errorMessage}`,
        };
        context.stageOutputs.set('deployment-generation', output);
        return output;
    }
}
//# sourceMappingURL=deployment-generator.js.map