#Requires -Version 7

<#
.SYNOPSIS
    Tags a release of the Go MxAccessGateway client module.

.DESCRIPTION
    Go modules in monorepo subdirectories use prefixed tags
    ("clients/go/v0.1.0") so `go get <module>@v0.1.0` resolves correctly.
    This script validates the version, creates the prefixed tag at HEAD,
    and (optionally) pushes it.

.PARAMETER Version
    Semver tag without the prefix, e.g. "v0.1.0".

.PARAMETER Push
    When set, pushes the tag to origin after creation.

.EXAMPLE
    pwsh scripts/tag-go-module.ps1 -Version v0.1.0
    pwsh scripts/tag-go-module.ps1 -Version v0.1.1 -Push
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string]$Version,

    [switch]$Push
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

if ($Version -notmatch '^v\d+\.\d+\.\d+(-[A-Za-z0-9.-]+)?$') {
    throw "Version '$Version' must match semver vX.Y.Z (optionally with -prerelease suffix)."
}

# CLI-21 guard: the tag must match what the module itself reports via
# ClientVersion, or `go get <module>@vX.Y.Z` resolves a tag whose module
# code disagrees with its own version constant.
$versionGoPath = Join-Path $PSScriptRoot '..' 'clients/go/mxgateway/version.go'
if (-not (Test-Path $versionGoPath)) {
    throw "Could not find '$versionGoPath' to verify ClientVersion before tagging."
}
$versionGoContent = Get-Content $versionGoPath -Raw
if ($versionGoContent -notmatch 'ClientVersion\s*=\s*"([^"]+)"') {
    throw "Could not find a ClientVersion = `"...`" constant in '$versionGoPath'."
}
$clientVersion = $Matches[1]
$tagVersion = $Version.TrimStart('v')
if ($clientVersion -ne $tagVersion) {
    throw "clients/go/mxgateway/version.go ClientVersion is '$clientVersion' but the requested tag is '$tagVersion'. Update ClientVersion to match before tagging."
}

$tag = "clients/go/$Version"
Write-Host "Creating Go-module tag: $tag" -ForegroundColor Cyan

# Verify we're on a clean checkout — refuse to tag with uncommitted tracked
# changes. Test each porcelain line individually: any entry that is not an
# untracked file (`??`) is a tracked change, regardless of how the entries
# happen to sort. Joining and anchoring `^\?\?` against the whole blob would
# only inspect the first line and miss tracked changes behind an untracked one.
$dirty = (git status --porcelain) | Where-Object { $_ -and ($_ -notmatch '^\?\?') }
if ($dirty) {
    throw "Working tree has tracked changes. Commit or stash before tagging.`n$($dirty -join "`n")"
}

# Verify the tag doesn't already exist.
$existing = git tag --list $tag
if ($existing) {
    throw "Tag '$tag' already exists. Use a new version."
}

git tag -a $tag -m "Go client release $Version"
Write-Host "Created tag: $tag" -ForegroundColor Green

if ($Push) {
    git push origin $tag
    Write-Host "Pushed tag to origin." -ForegroundColor Green
} else {
    Write-Host "Tag not pushed. To publish, run: git push origin $tag" -ForegroundColor Yellow
}
