#!/usr/bin/env nu

# Platform compilation tool - compiles all Rust components for distribution
#
# Compiles:
# - orchestrator (provisioning-orchestrator binary)
# - control-center (control center API)
# - control-center-ui (web UI)
# - mcp-server-rust (MCP integration)

use std log

def main [
    --target: string = "x86_64-unknown-linux-gnu"  # Target platform
    --release                                      # Build in release mode
    --features: string = ""                        # Comma-separated features to enable
    --output-dir: string = "dist/platform"         # Output directory for binaries
    --verbose                                      # Enable verbose logging
    --clean                                        # Clean before building
] {

    let repo_root = ($env.PWD | path dirname | path dirname | path dirname)
    let build_config = {
        target: $target
        release: $release
        features: ($features | if $in == "" { [] } else { $in | split column "," | get column1 })
        output_dir: ($output_dir | path expand)
        verbose: $verbose
        clean: $clean
    }

    log info $"Starting platform compilation with config: ($build_config)"

    # Ensure output directory exists
    mkdir ($build_config.output_dir)

    let rust_projects = [
        {
            name: "orchestrator"
            path: ($repo_root | path join "orchestrator")
            binary: "provisioning-orchestrator"
            features: ["surrealdb"]
        },
        {
            name: "control-center"
            path: ($repo_root | path join "control-center")
            binary: "control-center"
            features: []
        },
        {
            name: "control-center-ui"
            path: ($repo_root | path join "control-center-ui")
            binary: "control-center-ui"
            features: []
        },
        {
            name: "mcp-server"
            path: ($repo_root | path join "provisioning" "mcp-server-rust")
            binary: "mcp-server-rust"
            features: []
        }
    ]

    let results = $rust_projects | each {|project|
        compile_rust_project $project $build_config $repo_root
    }

    let summary = {
        total: ($results | length)
        successful: ($results | where status == "success" | length)
        failed: ($results | where status == "failed" | length)
        build_config: $build_config
        results: $results
    }

    if $summary.failed > 0 {
        log error $"Platform compilation completed with ($summary.failed) failures"
        exit 1
    } else {
        log info $"Platform compilation completed successfully - all ($summary.total) components built"
    }

    return $summary
}

# Compile a single Rust project
def compile_rust_project [
    project: record
    build_config: record
    repo_root: string
] {
    log info $"Compiling ($project.name)..."

    if not ($project.path | path exists) {
        log warning $"Project path does not exist: ($project.path)"
        return {
            project: $project.name
            status: "skipped"
            reason: "path not found"
            binary_path: null
            duration: 0
        }
    }

    cd ($project.path)

    let start_time = (date now)

    # Clean if requested
    if $build_config.clean {
        log info $"Cleaning ($project.name)..."
        ^cargo clean
    }

    # Build cargo command
    let base_cmd = ["cargo", "build"]

    let release_flags = if $build_config.release { ["--release"] } else { [] }
    let target_flags = if $build_config.target != "native" { ["--target", $build_config.target] } else { [] }

    let all_features = ($build_config.features | append $project.features | uniq)
    let feature_flags = if ($all_features | length) > 0 { ["--features", ($all_features | str join ",")] } else { [] }

    let verbose_flags = if $build_config.verbose { ["--verbose"] } else { [] }

    let cargo_cmd = $base_cmd | append $release_flags | append $target_flags | append $feature_flags | append $verbose_flags

    # Execute build with error handling
    let build_result = do {
        ^$cargo_cmd.0 ...$cargo_cmd.1.. out+err> /tmp/cargo_build.log
    } | complete

    if $build_result.exit_code != 0 {
        log error $"Failed to compile ($project.name): ($build_result.stderr)"
        return {
            project: $project.name
            status: "failed"
            reason: $build_result.stderr
            binary_path: null
            duration: ((date now) - $start_time)
        }
    }

    # Determine binary path
    let profile = if $build_config.release { "release" } else { "debug" }
    let target_dir = if $build_config.target == "native" {
        $"target/($profile)"
    } else {
        $"target/($build_config.target)/($profile)"
    }

    let binary_path = ($project.path | path join $target_dir $project.binary)

    if ($binary_path | path exists) {
        # Copy binary to output directory
        let output_binary = ($build_config.output_dir | path join $"($project.name)-($build_config.target)")
        ^cp $binary_path $output_binary

        log info $"Successfully compiled ($project.name) -> ($output_binary)"

        {
            project: $project.name
            status: "success"
            binary_path: $output_binary
            source_path: $binary_path
            duration: ((date now) - $start_time)
            size: (ls $output_binary | get 0.size)
        }
    } else {
        log error $"Binary not found after build: ($binary_path)"
        {
            project: $project.name
            status: "failed"
            reason: "binary not found"
            binary_path: null
            duration: ((date now) - $start_time)
        }
    }
}

# Show build environment info
def "main info" [] {
    {
        rust_version: (rustc --version)
        cargo_version: (cargo --version)
        available_targets: (rustup target list --installed)
        default_target: (rustc -vV | grep "host:" | str replace "host: " "")
    }
}

# List available Rust projects
def "main list" [] {
    let repo_root = ($env.PWD | path dirname | path dirname | path dirname)

    [
        { name: "orchestrator", path: ($repo_root | path join "orchestrator"), status: (check_project_status ($repo_root | path join "orchestrator")) },
        { name: "control-center", path: ($repo_root | path join "control-center"), status: (check_project_status ($repo_root | path join "control-center")) },
        { name: "control-center-ui", path: ($repo_root | path join "control-center-ui"), status: (check_project_status ($repo_root | path join "control-center-ui")) },
        { name: "mcp-server", path: ($repo_root | path join "provisioning" "mcp-server-rust"), status: (check_project_status ($repo_root | path join "provisioning" "mcp-server-rust")) }
    ]
}

def check_project_status [path: string] {
    if not ($path | path exists) {
        return "missing"
    }

    if not (($path | path join "Cargo.toml") | path exists) {
        return "not-rust"
    }

    return "ready"
}
