#!/usr/bin/env nu

# Common Library for Nushell Plugins Distribution Scripts
# Provides shared utilities, logging, and validation functions

# Logging functions with consistent formatting
export def log_info [message: string] {
    print $"(ansi blue)ℹ️  ($message)(ansi reset)"
}

export def log_success [message: string] {
    print $"(ansi green)✅ ($message)(ansi reset)"
}

export def log_warn [message: string] {
    print $"(ansi yellow)⚠️  ($message)(ansi reset)"
}

export def log_error [message: string] {
    print $"(ansi red)❌ ($message)(ansi reset)"
}

export def log_debug [message: string] {
    if ($env.DEBUG? | default false) {
        print $"(ansi dim)🐛 DEBUG: ($message)(ansi reset)"
    }
}

# Validate nushell version consistency between system and workspace
export def validate_nushell_version [] {
    log_debug "Validating nushell version consistency..."

    # Check if nushell submodule exists
    let nushell_dir = "./nushell"
    if not ($nushell_dir | path exists) {
        log_error $"Nushell submodule not found at ($nushell_dir)"
        exit 1
    }

    # Get system nu version
    let system_version = try {
        (nu --version | str replace "nushell " "" | str replace " .*" "")
    } catch {
        log_error "Could not determine system nushell version"
        exit 1
    }

    # Get workspace nu version from Cargo.toml
    let cargo_toml_path = $"($nushell_dir)/Cargo.toml"
    let workspace_version = try {
        (open $cargo_toml_path | get package.version)
    } catch {
        log_error $"Could not read package version from ($cargo_toml_path)"
        exit 1
    }

    if $system_version != $workspace_version {
        log_error $"Version mismatch: system nu ($system_version) != workspace nu ($workspace_version)"
        log_info "Run 'just fix-nushell' to resolve version inconsistencies"
        exit 1
    }

    log_success $"Nushell version validation passed: ($system_version)"
}

# Get current platform identifier
export def get_current_platform [] {
    let os = (sys host | get name)
    let arch = (run-external "uname" "-m" | str trim)

    let platform_name = match $os {
        "Linux" => "linux",
        "Darwin" => "darwin",
        "Windows" => "windows",
        _ => ($os | str downcase)
    }

    let arch_name = match $arch {
        "x86_64" => "x86_64",
        "aarch64" => "arm64",
        "arm64" => "arm64",
        _ => $arch
    }

    $"($platform_name)-($arch_name)"
}

# Get all supported platforms
export def get_supported_platforms [] {
    [
        "linux-x86_64",
        "linux-arm64",
        "darwin-x86_64",
        "darwin-arm64",
        "windows-x86_64"
    ]
}

# Get binary extension for platform
export def get_binary_extension [platform: string] {
    if ($platform | str starts-with "windows") {
        ".exe"
    } else {
        ""
    }
}

# Get archive extension for platform
export def get_archive_extension [platform: string] {
    if ($platform | str starts-with "windows") {
        ".zip"
    } else {
        ".tar.gz"
    }
}

# Ensure directory exists
export def ensure_dir [path: string] {
    if not ($path | path exists) {
        mkdir $path
        log_info $"Created directory: ($path)"
    }
}

# Remove directory if it exists
export def remove_dir [path: string] {
    if ($path | path exists) {
        rm -rf $path
        log_info $"Removed directory: ($path)"
    }
}

# Copy file with logging
export def copy_file [src: string, dest: string] {
    if not ($src | path exists) {
        log_error $"Source file does not exist: ($src)"
        return false
    }

    let dest_dir = ($dest | path dirname)
    ensure_dir $dest_dir

    cp $src $dest
    log_debug $"Copied ($src) -> ($dest)"
    true
}

# Create checksums for files
export def create_checksums [files: list<string>, output_dir: string] {
    let checksum_file = $"($output_dir)/checksums.txt"

    let checksums = $files | each {|file|
        if ($file | path exists) {
            let hash = (open $file --raw | hash sha256)
            let filename = ($file | path basename)
            $"($hash)  ($filename)"
        }
    } | compact

    $checksums | save -f $checksum_file
    log_success $"Created checksums file: ($checksum_file)"
}

# Detect available plugin directories
export def get_plugin_directories [] {
    glob "nu_plugin_*" | where {|it| ($it | path exists) and (($it | path type) == "dir")}
}

# Get plugin name from directory
export def get_plugin_name [dir: string] {
    $dir | path basename
}

# Check if path is a plugin directory
export def is_plugin_directory [path: string] {
    ($path | path basename | str starts-with "nu_plugin_") and ($path | path type) == "dir"
}

# Get version from current workspace
export def get_workspace_version [] {
    let version_from_git = try {
        (git describe --tags --abbrev=0 2>/dev/null | str replace "^v" "")
    } catch {
        ""
    }

    if ($version_from_git | str length) > 0 {
        $version_from_git
    } else {
        # Fallback to version from nushell Cargo.toml
        try {
            (open "./nushell/Cargo.toml" | get package.version)
        } catch {
            "0.1.0"
        }
    }
}

# Create manifest for distribution
export def create_manifest [
    version: string,
    platform: string,
    components: record,
    output_file: string
] {
    let manifest = {
        version: $version,
        platform: $platform,
        created_at: (date now | format date "%Y-%m-%d %H:%M:%S UTC"),
        components: $components,
        nushell_version: (try { (nu --version) } catch { "unknown" })
    }

    $manifest | to json | save -f $output_file
    log_success $"Created manifest: ($output_file)"
}

# Parse command line flags into structured data
export def parse_flags [args: list] {
    mut flags = {}

    mut i = 0
    while $i < ($args | length) {
        let arg = ($args | get $i)

        if ($arg | str starts-with "--") {
            let flag_name = ($arg | str replace "--" "")

            # Check if next arg is a value or another flag
            let next_i = ($i + 1)
            if $next_i < ($args | length) {
                let next_arg = ($args | get $next_i)
                if not ($next_arg | str starts-with "--") {
                    $flags = ($flags | insert $flag_name $next_arg)
                    $i = ($i + 2)
                } else {
                    $flags = ($flags | insert $flag_name true)
                    $i = ($i + 1)
                }
            } else {
                $flags = ($flags | insert $flag_name true)
                $i = ($i + 1)
            }
        } else {
            $i = ($i + 1)
        }
    }

    $flags
}

# Execute command with error handling
export def exec_with_error [command: string] {
    log_debug $"Executing: ($command)"

    let result = try {
        (bash -c $command)
    } catch {|err|
        log_error $"Command failed: ($command)"
        log_error $"Error: ($err.msg)"
        exit 1
    }

    $result
}

# Check if binary exists and is executable
export def check_binary [path: string] {
    if not ($path | path exists) {
        false
    } else if ($path | path type) != "file" {
        false
    } else {
        # On Unix-like systems, check if executable
        if (sys host | get name) != "Windows" {
            try {
                (ls -l $path | get 0.mode | str contains "x")
            } catch {
                false
            }
        } else {
            true
        }
    }
}