#!/usr/bin/env nu
# {{ project_name }} - TypeDialog Nickel Roundtrip Configuration Script (Nushell)
#
# This script integrates TypeDialog forms with Nickel configuration:
# 1. Runs TypeDialog form to collect user input (JSON output)
# 2. Converts JSON to Nickel configuration
# 3. Validates Nickel configuration against schemas
# 4. Merges with defaults and applies type contracts

# Configuration paths
const FORM_PATH = "{{ form_path }}"
const CONFIG_PATH = "{{ config_path }}"
const TEMPLATE_PATH = "{{ template_path }}"
const GENERATED_DIR = "generated"

# Color formatting
def log-info [message: string] {
    print $"(ansi blue)[INFO](ansi reset) ($message)"
}

def log-success [message: string] {
    print $"(ansi green)[SUCCESS](ansi reset) ($message)"
}

def log-warn [message: string] {
    print $"(ansi yellow)[WARN](ansi reset) ($message)"
}

def log-error [message: string] {
    print $"(ansi red)[ERROR](ansi reset) ($message)"
}

# Check if command exists
def command-exists [cmd: string]: nothing -> bool {
    (which $cmd | length) > 0
}

# Check dependencies
def check-dependencies []: nothing -> nothing {
    let missing = [
        "typedialog",
        "nickel"
    ] | filter {|cmd| not (command-exists $cmd)}

    if ($missing | length) > 0 {
        log-error $"Missing required dependencies: ($missing | str join ', ')"
        log-info "Install with: cargo install typedialog nickel"
        error make {msg: "Missing dependencies"}
    }
}

# Step 1: Run TypeDialog form
def run-form []: nothing -> nothing {
    log-info $"Running TypeDialog form: ($FORM_PATH)"

    if not ($FORM_PATH | path exists) {
        log-error $"Form file not found: ($FORM_PATH)"
        error make {msg: "Form file not found"}
    }

    mkdir $GENERATED_DIR

    try {
        ^typedialog $FORM_PATH --output-format json --output $"($GENERATED_DIR)/user-input.json"
        log-success $"User input captured: ($GENERATED_DIR)/user-input.json"
    } catch {|err|
        log-error "TypeDialog form execution failed"
        error make {msg: $"Form failed: ($err)"}
    }
}

# Step 2: Convert JSON to Nickel
def json-to-nickel []: nothing -> nothing {
    log-info "Converting JSON to Nickel configuration"

    let json_file = $"($GENERATED_DIR)/user-input.json"
    let nickel_file = $"($GENERATED_DIR)/config.ncl"

    if not ($json_file | path exists) {
        log-error $"JSON input file not found: ($json_file)"
        error make {msg: "JSON input not found"}
    }

    let timestamp = (date now | format date "%Y-%m-%dT%H:%M:%SZ")
    let user_json = (open $json_file)

    # Generate Nickel configuration with embedded JSON
    let nickel_content = $"# Generated Nickel configuration from TypeDialog form
# Generated at: ($timestamp)

let schemas = import \"../schemas/config.ncl\" in
let defaults = import \"../defaults/config.ncl\" in
let validators = import \"../validators/config.ncl\" in

# User-provided values \(from TypeDialog form\)
let user_values = ($user_json | to json) in

# Merge user values with defaults and apply type contracts
let final_config = std.record.merge defaults user_values in

# Apply validators
let validated_config = validators.validate final_config in

validated_config | schemas.Config"

    $nickel_content | save --force $nickel_file
    log-success $"Nickel configuration generated: ($nickel_file)"
}

# Step 3: Validate Nickel configuration
def validate-nickel []: nothing -> nothing {
    log-info "Validating Nickel configuration"

    let nickel_file = $"($GENERATED_DIR)/config.ncl"

    # Type checking
    try {
        ^nickel typecheck $nickel_file
        log-success "Nickel type checking passed"
    } catch {|err|
        log-error "Nickel type checking failed"
        error make {msg: $"Type check failed: ($err)"}
    }

    # Test evaluation
    try {
        ^nickel export $nickel_file | ignore
        log-success "Nickel evaluation succeeded"
    } catch {|err|
        log-error "Nickel evaluation failed"
        error make {msg: $"Evaluation failed: ($err)"}
    }
}

# Step 4: Export to final formats
def export-config []: nothing -> nothing {
    log-info "Exporting configuration to final formats"

    let nickel_file = $"($GENERATED_DIR)/config.ncl"

    # Export to JSON
    try {
        ^nickel export --format json $nickel_file | save --force $"($GENERATED_DIR)/config.json"
        log-success $"Exported: ($GENERATED_DIR)/config.json"
    } catch {|err|
        log-error $"JSON export failed: ($err)"
    }

    # Export to YAML
    try {
        ^nickel export --format yaml $nickel_file | save --force $"($GENERATED_DIR)/config.yaml"
        log-success $"Exported: ($GENERATED_DIR)/config.yaml"
    } catch {|err|
        log-error $"YAML export failed: ($err)"
    }

    # Export to TOML (convert from JSON)
    if (command-exists "json2toml") {
        try {
            open $"($GENERATED_DIR)/config.json" | ^json2toml | save --force $"($GENERATED_DIR)/config.toml"
            log-success $"Exported: ($GENERATED_DIR)/config.toml"
        } catch {|err|
            log-warn $"TOML export failed: ($err)"
        }
    } else {
        log-warn "json2toml not found, skipping TOML export"
    }
}

# Main execution
def main []: nothing -> nothing {
    log-info "Starting {{ project_name }} configuration"

    check-dependencies
    run-form
    json-to-nickel
    validate-nickel
    export-config

    log-success "Configuration complete!"
    log-info $"Generated files in: ($GENERATED_DIR)/"
    log-info "  - config.ncl (Nickel source)"
    log-info "  - config.json (JSON export)"
    log-info "  - config.yaml (YAML export)"
}

main
