// epm/src/epm.el — El Package Manager entry point
//
// epm manages vessels: versioned El source packages backed by Gitea releases.
// Each vessel corresponds to a Gitea repository under a shared org. Versions
// are Gitea release tags; source archives are attached as release assets named
// "<name>-<version>.tar.gz".
//
// Vessels are installed to ~/.el/packages/<name>/<version>/.
// The installed registry lives at ~/.el/packages/installed.json.
//
// Usage:
//   epm publish                   # publish current project to registry
//   epm install                   # install all dependencies from manifest.el
//   epm install <vessel>          # install a specific vessel (latest)
//   epm install <vessel>@<ver>    # install a specific vessel at a version
//   epm list                      # list installed vessels
//   epm info <vessel>             # show metadata for a vessel
//   epm info <vessel> <version>   # show metadata for a specific version
//   epm update                    # update all installed vessels
//   epm update <vessel>           # update a specific vessel
//   epm check                     # check for available updates (no install)
//
// Configuration (environment):
//   EPM_GITEA_API    — Gitea API base URL (default: https://git.neuralplatform.ai/api/v1)
//   EPM_REGISTRY_ORG — org hosting vessel repos (default: neuron-technologies)
//   EPM_TOKEN        — Gitea personal access token (required for publish)
//
// Import order: manifest.el, registry.el, install.el, update.el must be
// compiled first. This file imports all four and is the build entry point.

import "manifest.el"
import "registry.el"
import "install.el"
import "update.el"

// ── Subcommand handlers ───────────────────────────────────────────────────────

// cmd_publish reads manifest.el from the current directory and publishes
// the vessel to the Gitea registry as a release.
fn cmd_publish() -> Void {
    let src: String = fs_read("manifest.el")
    if str_eq(src, "") {
        println("epm: no manifest.el found in current directory")
        exit(1)
    }

    let name: String = manifest_name(src)
    if str_eq(name, "") {
        println("epm: manifest.el has no 'vessel' or 'package' declaration")
        exit(1)
    }

    let version: String = manifest_version(src)
    if str_eq(version, "") {
        println("epm: manifest.el has no 'version' declaration")
        exit(1)
    }

    let description: String = manifest_description(src)
    let entry: String       = manifest_entry(src)
    let deps_json: String   = manifest_deps(src)

    println("epm: publishing " + name + " " + version + " ...")

    let release_id: String = registry_publish(name, version, description, entry, deps_json)
    if str_eq(release_id, "") {
        println("epm: publish failed")
        exit(1)
    }

    println("epm: published " + name + " " + version + " (release: " + release_id + ")")
}

// cmd_install_named installs a specific vessel by name (with optional version).
// Expects: install <name> or install <name>@<version>
fn cmd_install_named(spec: String) -> Void {
    // spec may be "el-auth" or "el-auth@0.1.0"
    let at: Int = str_index_of(spec, "@")
    let vname: String = spec
    let vver: String  = ""
    if at > 0 {
        let vname = str_slice(spec, 0, at)
        let vver  = str_slice(spec, at + 1, str_len(spec))
    }

    println("epm: installing " + vname + " ...")

    let ok: Bool = install_vessel(vname, vver)
    if !ok {
        println("epm: install failed")
        exit(1)
    }

    // Notify about other available updates after a successful install
    let outdated: Int = check_updates()
    if outdated > 0 {
        println("")
        println("  note: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
    }
}

// cmd_list prints all locally installed vessels.
fn cmd_list() -> Void {
    let installed: String = read_installed()
    if str_eq(installed, "") {
        println("epm: no vessels installed")
        return
    }
    if str_eq(installed, "{}") {
        println("epm: no vessels installed")
        return
    }

    let inner_len: Int = str_len(installed)
    if inner_len < 2 {
        println("epm: no vessels installed")
        return
    }
    let body: String = str_slice(installed, 1, inner_len - 1)
    let body_trimmed: String = str_trim(body)
    if str_eq(body_trimmed, "") {
        println("epm: no vessels installed")
        return
    }

    println("epm: installed vessels:")
    println("")

    let pairs: [String] = str_split(body_trimmed, ",")
    let pair_count: Int = native_list_len(pairs)
    let i: Int = 0
    while i < pair_count {
        let pair: String = str_trim(native_list_get(pairs, i))
        let colon: Int = str_index_of(pair, ":")
        if colon > 0 {
            let raw_key: String = str_trim(str_slice(pair, 0, colon))
            let raw_val: String = str_trim(str_slice(pair, colon + 1, str_len(pair)))
            let key_len: Int = str_len(raw_key)
            let val_len: Int = str_len(raw_val)
            let vname2: String = raw_key
            let vver2: String  = raw_val
            if str_starts_with(raw_key, "\"") {
                let vname2 = str_slice(raw_key, 1, key_len - 1)
            }
            if str_starts_with(raw_val, "\"") {
                let vver2 = str_slice(raw_val, 1, val_len - 1)
            }
            println("  " + vname2 + " " + vver2)
        }
        let i = i + 1
    }
}

// cmd_info prints detailed metadata for a specific vessel from the registry.
// argv is the full args list; idx is the position of the vessel name.
fn cmd_info(argv: [String], idx: Int) -> Void {
    let argc: Int = native_list_len(argv)
    if idx >= argc {
        println("epm: usage: epm info <vessel> [version]")
        exit(1)
    }

    let vname: String = native_list_get(argv, idx)
    let vver: String  = ""
    if idx + 1 < argc {
        let vver = native_list_get(argv, idx + 1)
    }

    let content: String = registry_find(vname, vver)
    if str_eq(content, "") {
        println("epm: vessel '" + vname + "' not found in registry")
        exit(1)
    }

    let name: String   = json_get_string(content, "name")
    let ver: String    = json_get_string(content, "version")
    let desc: String   = json_get_string(content, "description")
    let dl_url: String = json_get_string(content, "download_url")

    println("name:        " + name)
    println("version:     " + ver)
    println("description: " + desc)
    println("download:    " + dl_url)

    let local_ver: String = installed_version(name)
    if !str_eq(local_ver, "") {
        println("installed:   " + local_ver)
    } else {
        println("installed:   (not installed)")
    }
}

// ── Main ──────────────────────────────────────────────────────────────────────

fn main() -> Void {
    let argv: [String] = args()
    let argc: Int = native_list_len(argv)

    // argv[0] is the program name; subcommand is argv[1]
    if argc < 2 {
        println("epm — El Package Manager")
        println("")
        println("usage:")
        println("  epm publish                   publish current project to registry")
        println("  epm install                   install all dependencies (from manifest.el)")
        println("  epm install <vessel>          install a specific vessel (latest version)")
        println("  epm install <vessel>@<ver>    install a specific vessel at a version")
        println("  epm list                      list installed vessels")
        println("  epm info <vessel>             show vessel metadata from registry")
        println("  epm info <vessel> <version>   show metadata for a specific version")
        println("  epm update                    update all installed vessels")
        println("  epm update <vessel>           update a specific vessel")
        println("  epm check                     check for available updates (no install)")
        println("")
        println("configuration:")
        println("  EPM_GITEA_API    Gitea API base URL (default: https://git.neuralplatform.ai/api/v1)")
        println("  EPM_REGISTRY_ORG org hosting vessel repos (default: neuron-technologies)")
        println("  EPM_TOKEN        Gitea personal access token (required for publish)")
        exit(0)
    }

    let sub: String = native_list_get(argv, 1)

    if str_eq(sub, "publish") {
        cmd_publish()
        return
    }

    if str_eq(sub, "install") {
        if argc >= 3 {
            let spec: String = native_list_get(argv, 2)
            cmd_install_named(spec)
        } else {
            cmd_install()
            // Notify about other available updates after a successful install
            let outdated: Int = check_updates()
            if outdated > 0 {
                println("")
                println("  note: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
            }
        }
        return
    }

    if str_eq(sub, "list") {
        cmd_list()
        return
    }

    if str_eq(sub, "info") {
        cmd_info(argv, 2)
        return
    }

    if str_eq(sub, "update") {
        if argc >= 3 {
            let vessel_arg: String = native_list_get(argv, 2)
            cmd_update(vessel_arg)
        } else {
            cmd_update("")
        }
        return
    }

    if str_eq(sub, "check") {
        println("epm: checking for updates ...")
        let outdated: Int = check_updates()
        if outdated == 0 {
            println("epm: all installed vessels are up to date")
        } else {
            println("")
            println("epm: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
        }
        return
    }

    println("epm: unknown subcommand '" + sub + "'")
    println("run 'epm' with no arguments for usage")
    exit(1)
}
