# IaC to Orchestrator Integration
# Converts Infrastructure-from-Code output to orchestrator workflow definitions

# Convert IaC detection to orchestrator workflow
export def iac-to-workflow [
  detection: record
  completion: record
  --org: string = "default"
  --infra: string = "default"
  --mode: string = "sequential"  # sequential or parallel
] {
  # Extract detected technologies and inferred requirements
  let detected = if ($detection.detections? != null and ($detection.detections | is-not-empty)) {
    $detection.detections | each {|d| $d.technology}
  } else {
    []
  }

  let inferred = if ($completion.additional_requirements? != null and ($completion.additional_requirements | is-not-empty)) {
    $completion.additional_requirements
  } else {
    []
  }

  # Build dependency map for task ordering
  let dependencies = (build-dependency-map $detected $inferred)

  # Generate workflow definition
  {
    workflow: {
      name: $"Infrastructure deployment - ($org) - ($infra)"
      description: $"Auto-generated from IaC detection for ($detected | str join ', ')"
      version: "1.0.0"
      metadata: {
        source: "iac-detector"
        organization: $org
        infrastructure: $infra
        detected_technologies: $detected
        detected_count: ($detected | length)
        inferred_count: ($inferred | length)
        completeness: ($completion.completeness | default 0.0)
        timestamp: (date now | date format '%Y-%m-%dT%H:%M:%SZ')
      }

      execution_config: {
        strategy: $mode
        max_parallel: (if $mode == "parallel" { 4 } else { 1 })
        fail_fast: false
        timeout_seconds: 3600
      }

      phases: (generate-workflow-phases $detected $inferred $dependencies)
    }
  }
}

# Build dependency ordering
def build-dependency-map [
  detected: list
  inferred: list
] {
  # Define standard technology dependencies
  {
    # Data layer
    postgres: {
      depends_on: []
      must_precede: ["pg-backup" "pg-monitoring" "pgbouncer"]
    }
    mysql: {
      depends_on: []
      must_precede: ["mysql-backup" "mysql-monitoring"]
    }
    mongodb: {
      depends_on: []
      must_precede: ["mongo-backup" "mongo-monitoring"]
    }
    redis: {
      depends_on: []
      must_precede: []
    }

    # Application layer
    nodejs: {
      depends_on: []
      must_precede: ["nginx" "monitoring"]
    }
    python: {
      depends_on: []
      must_precede: ["gunicorn" "monitoring"]
    }
    java: {
      depends_on: []
      must_precede: ["jvm-monitoring" "monitoring"]
    }

    # Infrastructure
    docker: {
      depends_on: []
      must_precede: ["kubernetes"]
    }
    kubernetes: {
      depends_on: ["docker"]
      must_precede: []
    }

    # Services
    nginx: {
      depends_on: ["nodejs" "python"]
      must_precede: []
    }
    monitoring: {
      depends_on: []
      must_precede: []
    }
    backup: {
      depends_on: ["postgres" "mysql" "mongodb"]
      must_precede: []
    }
  }
}

# Generate workflow phases based on dependencies
def generate-workflow-phases [
  detected: list
  inferred: list
  dependencies: record
] {
  # Phase 1: Setup base infrastructure
  let phase1_tasks = ($detected | where {|t|
    ($t in ["postgres" "mysql" "mongodb" "redis" "docker"])
  } | each {|tech|
    {
      id: $"setup-($tech)"
      type: "taskserv-deploy"
      params: {
        service_name: $tech
        version: "latest"
        wait_for_ready: true
      }
    }
  })

  # Phase 2: Deploy inferred services
  let phase2_tasks = ($inferred | each {|req|
    let service = $req.taskserv
    let deps = if (($dependencies | get $service)?.depends_on? != null and ((($dependencies | get $service).depends_on) | is-not-empty)) {
      (($dependencies | get $service).depends_on | each {|d| $"setup-\($d)"})
    } else {
      []
    }

    {
      id: $"deploy-($service)"
      type: "taskserv-deploy"
      params: {
        service_name: $service
        version: "latest"
        wait_for_ready: true
      }
      depends_on: $deps
      metadata: {
        confidence: $req.confidence
        required: $req.required
        reason: $req.reason
      }
    }
  })

  # Phase 3: Configure and validate
  let phase3_tasks = [
    {
      id: "validate-deployment"
      type: "validation"
      params: {
        check_all_services: true
        verify_networking: true
      }
      depends_on: ([$phase1_tasks $phase2_tasks] | flatten | each {|t| $t.id})
    }
    {
      id: "generate-report"
      type: "reporting"
      params: {
        format: "json"
        include_metrics: true
      }
      depends_on: ["validate-deployment"]
    }
  ]

  # Combine all tasks
  [$phase1_tasks, $phase2_tasks, $phase3_tasks] | flatten
}

# Export workflow to Nickel format for orchestrator
export def export-workflow-nickel [workflow] {
  # Handle both direct workflow and nested structure
  let w = ($workflow.workflow? | default $workflow)

  # Build header
  let header = (
    "// Auto-generated infrastructure workflow\n" +
    "// Source: Infrastructure-from-Code detection\n" +
    "// Generated: " + ($w.metadata.timestamp | default (date now | date format '%Y-%m-%dT%H:%M:%SZ')) + "\n\n" +
    "workflow \"" + $w.name + "\" {\n" +
    "    metadata = {\n" +
    "        description = \"" + $w.description + "\"\n" +
    "        organization = \"" + $w.metadata.organization + "\"\n" +
    "        infrastructure = \"" + $w.metadata.infrastructure + "\"\n" +
    "        completeness = " + ($w.metadata.completeness | into string) + "\n" +
    "    }\n\n" +
    "    config {\n" +
    "        strategy = \"" + $w.execution_config.strategy + "\"\n" +
    "        max_parallel = " + ($w.execution_config.max_parallel | into string) + "\n" +
    "        timeout_seconds = " + ($w.execution_config.timeout_seconds | into string) + "\n" +
    "    }\n\n" +
    "    tasks = [\n"
  )

  # Build tasks section
  let tasks = $w.tasks | each {|task|
    let task_body = (
      "        {\n" +
      "            id = \"" + $task.id + "\"\n" +
      "            type = \"" + $task.type + "\"\n" +
      "            params = '" + ($task.params | to json) + "'\n"
    )

    let with_deps = (
      let depends_on_val = ($task.depends_on? | default null)
      if ($depends_on_val != null and ($depends_on_val | is-not-empty)) {
        (
          $task_body +
          "            depends_on = [\"" + ($task.depends_on | str join "\", \"") + "\"]\n"
        )
      } else {
        $task_body
      }
    )

    $with_deps + "        }"
  } | str join ",\n"

  # Build footer
  let footer = "\n    ]\n}\n"

  # Combine all parts
  $header + $tasks + $footer
}

# Submit workflow to orchestrator
export def submit-to-orchestrator [
  workflow: record
  --orchestrator-url: string = "http://localhost:8080"
  --dry-run
] {
  let workflow_json = ($workflow | to json)

  if $dry_run {
    print "Dry-run mode - would submit:"
    print ($workflow_json | from json | to json --indent 2)
    return {
      status: "dry-run"
      submitted: false
      workflow: $workflow
    }
  }

  # POST to orchestrator
  print "📤 Submitting workflow to orchestrator..."

  let result = (
    curl -X POST
      $"($orchestrator_url)/api/workflows"
      -H "Content-Type: application/json"
      -d $workflow_json
      --silent
  )

  if ($result | is-empty) {
    {
      status: "error"
      message: "Failed to connect to orchestrator"
      submitted: false
    }
  } else {
    let json_result = (do { from json $result } | complete)
    if $json_result.exit_code != 0 {
      {
        status: "error"
        message: $result
        submitted: false
      }
    } else {
      let response = ($json_result.stdout)
      {
        status: "success"
        submitted: true
        workflow_id: ($response.id | default "")
        message: "Workflow submitted successfully"
      }
    }
  }
}

# Monitor workflow execution
export def monitor-workflow [
  workflow_id: string
  --orchestrator-url: string = "http://localhost:8080"
  --poll-interval: int = 5
  --timeout: int = 3600
] {
  let start_time = (date now)
  let elapsed = 0

  while ($elapsed < $timeout) {
    let response = (
      curl $"($orchestrator_url)/api/workflows/($workflow_id)"
        -s
    )

    let workflow_status = (echo $response | from json)

    print $"Status: ($workflow_status.status)"
    print $"Progress: ($workflow_status.progress)%"
    print $"Time elapsed: ($elapsed)s"
    print ""

    if ($workflow_status.status == "completed" or $workflow_status.status == "failed") {
      return $workflow_status
    }

    sleep ($poll_interval | into duration)
    let elapsed = ((date now) - $start_time | into int)
  }

  {
    status: "timeout"
    message: "Workflow execution timed out"
  }
}

# Complete end-to-end: detect → complete → workflow
export def orchestrate-from-iac [
  project_path: string
  --org: string = "default"
  --infra: string = "default"
  --orchestrator-url: string = "http://localhost:8080"
  --dry-run
  --verbose
] {
  print ""
  print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  print "🔄 IaC-Driven Orchestration Pipeline"
  print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  print ""

  # Step 1: Detection
  print "STEP 1: Technology Detection"
  print "───────────────────────────"
  let detector_bin = if ($env.PROVISIONING? | is-not-empty) {
    $env.PROVISIONING | path join "platform" "target" "release" "provisioning-detector"
  } else {
    ($env.HOME | path join "project-provisioning/provisioning/platform/target/release/provisioning-detector")
  }

  let detect_result = (^$detector_bin detect $project_path --format json out+err>| complete)

  if $detect_result.exit_code != 0 {
    return {
      status: "error"
      stage: "detection"
      message: "Failed to detect technologies"
    }
  }

  let detection = ($detect_result.stdout | from json)
  print $"✓ Detected ($detection.detections | length) technologies"
  if $verbose {
    print "  Technologies:"
    $detection.detections | each {|d| print $"    - ($d.technology) (confidence: ($d.confidence))"}
  }
  print ""

  # Step 2: Completion
  print "STEP 2: Infrastructure Completion"
  print "─────────────────────────────────"
  let complete_result = (^$detector_bin complete $project_path --format json out+err>| complete)

  if $complete_result.exit_code != 0 {
    return {
      status: "error"
      stage: "completion"
      message: "Failed to analyze completeness"
    }
  }

  let completion = ($complete_result.stdout | from json)
  print $"✓ Completeness: ($completion.completeness)%"
  print $"✓ Changes needed: ($completion.changes_needed)"
  if $verbose {
    print $"  Summary: ($completion.change_summary)"
  }
  print ""

  # Step 3: Generate Workflow
  print "STEP 3: Workflow Generation"
  print "───────────────────────────"
  let workflow = (iac-to-workflow $detection $completion --org $org --infra $infra)
  print "✓ Generated workflow with ($workflow.workflow.phases | length) tasks"
  if $verbose {
    print "  Workflow name: ($workflow.workflow.name)"
    print "  Phases:"
    $workflow.workflow.phases | each {|p| print $"    - ($p.id)"}
  }
  print ""

  # Step 4: Submit to Orchestrator
  print "STEP 4: Submit to Orchestrator"
  print "──────────────────────────────"

  if $dry_run {
    print "🏃 DRY-RUN MODE - Not actually submitting"
    print ""
    print "Would submit workflow:"
    print ($workflow | to json --indent 2 | head -50)
    print "..."
    print ""
    return {
      status: "dry-run"
      workflow: $workflow
      message: "Dry-run complete - no changes applied"
    }
  }

  let submission = (submit-to-orchestrator $workflow --orchestrator-url $orchestrator_url)

  if $submission.submitted {
    print "✓ Workflow submitted to orchestrator"
    print $"  Workflow ID: ($submission.workflow_id)"
    print ""

    # Step 5: Monitor Execution
    print "STEP 5: Monitoring Execution"
    print "────────────────────────────"
    print "Waiting for orchestrator to complete deployment..."
    let final_status = (monitor-workflow $submission.workflow_id --orchestrator-url $orchestrator_url)

    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "✅ Orchestration Pipeline Complete"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ""

    $final_status
  } else {
    print "❌ Failed to submit workflow"
    print $"  Error: ($submission.message)"
    $submission
  }
}
