# VCS abstraction — detects jj or git from filesystem, exposes uniform operations.
#
# All ontoref modules should call these functions instead of hardcoding `git`
# commands. Detection is filesystem-based (no config, no env var): checks for
# `.jj/` (jj) and `.git/` (git) in ONTOREF_PROJECT_ROOT or ONTOREF_ROOT.

use ./env.nu

# Private: resolve project root following the same convention as other modules.
def project-root []: nothing -> string {
    let pr = ($env.ONTOREF_PROJECT_ROOT? | default "")
    if ($pr | is-not-empty) and ($pr != $env.ONTOREF_ROOT) { $pr } else { $env.ONTOREF_ROOT }
}

# Detect which VCS is active in the project root.
# Returns: "jj" | "git" | "none"
export def detect []: nothing -> string {
    let root = (project-root)
    let has_jj  = ($root | path join ".jj"  | path exists)
    let has_git = ($root | path join ".git" | path exists)
    if $has_jj { "jj" } else if $has_git { "git" } else { "none" }
}

# True when any VCS is active.
export def "is-repo" []: nothing -> bool {
    (detect) != "none"
}

# Get file content at last-committed state.
#
# jj model: the working copy IS a commit (@). Reading from @- gives the parent
# commit — i.e., the state before any current working-copy edits.
# `jj file show` requires jj >= 0.40.
export def "show-committed" [file_path: string]: nothing -> string {
    let root = (project-root)
    match (detect) {
        "jj" => {
            let rel = ($file_path | path relative-to $root)
            do { ^jj --no-pager --repository $root file show $rel -r "@-" } | complete
            | if $in.exit_code == 0 { $in.stdout } else { "" }
        },
        "git" => {
            let rel = ($file_path | path relative-to $root)
            do { ^git -C $root show $"HEAD:($rel)" } | complete
            | if $in.exit_code == 0 { $in.stdout } else { "" }
        },
        _ => { "" }
    }
}

# Revert a file to its last-committed state.
#
# jj: `jj restore --from @-` undoes working-copy edits for the given file.
# git: `git checkout -- <file>` restores from HEAD.
export def "restore-file" [file_path: string]: nothing -> nothing {
    let root = (project-root)
    match (detect) {
        "jj" => {
            let rel = ($file_path | path relative-to $root)
            do { ^jj --no-pager --repository $root restore --from "@-" -- $rel } | complete | ignore
        },
        "git" => {
            do { ^git -C $root checkout -- $file_path } | complete | ignore
        },
        _ => {
            error make { msg: $"vcs restore-file: no VCS at ($root)" }
        }
    }
}

# Get the remote origin URL.
export def "remote-url" []: nothing -> string {
    let root = (project-root)
    match (detect) {
        "jj" => {
            let r = do { ^jj --no-pager --repository $root git remote list } | complete
            if $r.exit_code != 0 or ($r.stdout | str trim | is-empty) { return "" }
            # Format: "<name> <url>" per line — extract URL from first remote
            $r.stdout | lines | where { |l| ($l | str trim | is-not-empty) }
            | first | split row "\t" | last | str trim
        },
        "git" => {
            let r = do { ^git -C $root remote get-url origin } | complete
            if $r.exit_code == 0 { $r.stdout | str trim } else { "" }
        },
        _ => { "" }
    }
}

# Get the current branch or bookmark name.
#
# jj: returns the bookmark pointing to @, or "detached" if none.
# git: returns the branch name from rev-parse.
export def "current-ref" []: nothing -> string {
    let root = (project-root)
    match (detect) {
        "jj" => {
            let r = do {
                ^jj --no-pager --repository $root bookmark list --pointing-to "@" -T "name ++ \"\\n\""
            } | complete
            if $r.exit_code != 0 { return "detached" }
            let names = ($r.stdout | lines | where { |l| ($l | str trim | is-not-empty) })
            if ($names | is-empty) { "detached" } else { $names | first }
        },
        "git" => {
            let r = do { ^git -C $root rev-parse --abbrev-ref HEAD } | complete
            if $r.exit_code == 0 { $r.stdout | str trim } else { "unknown" }
        },
        _ => { "unknown" }
    }
}

# True when the project root has a VCS remote configured.
export def "has-remote" []: nothing -> bool {
    (remote-url) | is-not-empty
}
