# Common utilities for gitlink-cli workflow scripts (PowerShell 5.1+)

# Force UTF-8 when capturing stdout from native commands.
# On Windows Chinese locales, PS 5.1 defaults to GBK and corrupts multi-byte
# JSON (e.g. 紧急/新增), which makes ConvertFrom-Json fail silently.
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8

# CRITICAL: gitlink-cli outputs UTF-8 JSON, but PS 5.1 on Chinese Windows
# defaults to GBK (codepage 936) for decoding external program output.
# Without this, multi-byte UTF-8 chars get garbled and JSON parsing fails.
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# Detect the gitlink-cli executable.
#   Windows: prefer the repo-local build at ..\..\gitlink-cli.exe (two dirs up
#            from lib/); bare 'gitlink-cli' is not on PATH in dev checkouts.
#   Unix / global npm install: fall back to bare 'gitlink-cli' on PATH.
if ($env:OS -eq "Windows_NT") {
    $localExe = Join-Path $PSScriptRoot "..\..\gitlink-cli.exe"
    $Script:GL = if (Test-Path $localExe) { $localExe } else { "gitlink-cli" }
} else {
    $Script:GL = "gitlink-cli"
}

# -- Logging --
function Log-Step  { param([string]$Msg) Write-Host "[STEP] $Msg" -ForegroundColor Blue }
function Log-Ok    { param([string]$Msg) Write-Host "[  OK] $Msg" -ForegroundColor Green }
function Log-Warn  { param([string]$Msg) Write-Host "[WARN] $Msg" -ForegroundColor Yellow }
function Log-Err   { param([string]$Msg) Write-Host "[ ERR] $Msg" -ForegroundColor Red }
function Log-Info  { param([string]$Msg) Write-Host "[INFO] $Msg" -ForegroundColor Cyan }
function Log-Title { param([string]$Msg) Write-Host ""; Write-Host "====== $Msg ======" -ForegroundColor White; Write-Host "" }
function Divider   { Write-Host "------------------------------------------------" -ForegroundColor Cyan }

# -- Auth Check --
function Check-Auth {
    if ($env:GITLINK_TOKEN) {
        Log-Ok "GITLINK_TOKEN is set"
        return
    }
    $status = & $Script:GL auth status 2>&1
    $statusStr = $status -join " "
    if ($statusStr -match "logged in") {
        Log-Ok "Authenticated"
        return
    }
    Log-Err "Not authenticated. Please login first:"
    Log-Info "  gitlink-cli auth login"
    Log-Info '  $env:GITLINK_TOKEN = "your-private-token"'
    exit 1
}

# -- CLI Wrapper --
# Returns raw JSON string on success, "" on failure.
# Callers do their own ConvertFrom-Json so they control error handling.
function Invoke-GL {
    param([string[]]$Arguments)
    # Suppress stderr to keep JSON output clean (errors go to console via error stream)
    $output = & $Script:GL @Arguments --format json 2>$null
    if ($output) { return ($output -join "`n") }
    return ""
}

# Like Invoke-GL but logs error on failure and returns parsed JSON object ($null on failure).
function Invoke-GLCheck {
    param([string[]]$Arguments)
    $output = Invoke-GL $Arguments
    if (-not $output) {
        Log-Err "Command returned no output: $Script:GL $($Arguments -join ' ')"
        return $null
    }
    try {
        $json = $output | ConvertFrom-Json
        if (-not $json.ok) {
            $errMsg = if ($json.error.message) { $json.error.message } else { "unknown error" }
            Log-Err "Command failed: $Script:GL $($Arguments -join ' ')"
            Log-Err $errMsg
            return $null
        }
        return $json
    } catch {
        Log-Err "Command failed (non-JSON response): $Script:GL $($Arguments -join ' ')"
        Log-Err $output
        return $null
    }
}

# -- JSON Helpers --
function Get-JsonOk {
    param($Json)
    return ($Json.ok -eq $true)
}

# -- CI / 流水线 --
# Fetch a repo's CI/流水线 pipelines from GitLink.
# NOTE: the `ci +builds` shortcut targets GET /{owner}/{repo}/builds, which the
# live server rejects with {"status":-1,"message":"接口数据异常"} (the endpoint
# does not exist on the current platform). The real CI endpoint is
# GET /v1/{owner}/{repo}/pipelines. We call it directly via the `api` subcommand.
# Returns the pipelines array, or @() on any error / no data. Never logs an
# error, because "CI not configured" or "no access" is a normal, non-fatal case.
function Get-CIPipelines {
    param([string]$Owner, [string]$Repo)
    $raw = Invoke-GL @("api", "GET", "/v1/$Owner/$Repo/pipelines")
    if (-not $raw) { return @() }
    try {
        $obj = $raw | ConvertFrom-Json
        if ($obj.ok -and $obj.data.pipelines) { return @($obj.data.pipelines) }
    } catch {}
    return @()
}

# Test whether a CI pipeline/build record represents a successful run.
# Checks the common status field names GitLink may use; tolerant because the
# pipeline object schema is not always observable.
function Test-CISuccess {
    param($Item)
    $s = if ($Item.status) { "$($Item.status)" }
          elseif ($Item.event) { "$($Item.event)" }
          elseif ($Item.state) { "$($Item.state)" }
          elseif ($Item.build_status) { "$($Item.build_status)" }
          else { "" }
    return ($s -eq "success" -or $s -eq "completed" -or $s -eq "passed" -or $s -eq "succeeded")
}

# -- Owner/Repo Detection --
function Detect-OwnerRepo {
    $remote = git remote get-url origin 2>$null
    if (-not $remote) {
        Log-Err "No git remote 'origin' found. Use -Owner and -Repo flags."
        exit 1
    }
    if ($remote -match "gitlink\.org\.cn[:/]([^/]+)/([^/.]+)") {
        return @{ Owner = $Matches[1]; Repo = $Matches[2] }
    }
    Log-Err "Cannot parse owner/repo from remote: $remote"
    exit 1
}

function Resolve-OwnerRepo {
    param([string]$Owner, [string]$Repo)
    if (-not $Owner -or -not $Repo) {
        $detected = Detect-OwnerRepo
        if (-not $Owner) { $Owner = $detected.Owner }
        if (-not $Repo) { $Repo = $detected.Repo }
    }
    Log-Info "Using: $Owner/$Repo"
    return @{ Owner = $Owner; Repo = $Repo }
}

# -- Date Helpers --
function Get-DateToday { return (Get-Date -Format "yyyy-MM-dd") }

Export-ModuleMember -Function *
