param(
    [switch]$AllowDirty
)

$ErrorActionPreference = "Stop"

function Write-Step($message) {
    Write-Host ""
    Write-Host "==> $message" -ForegroundColor Cyan
}

function Require-Command($name) {
    $command = Get-Command $name -ErrorAction SilentlyContinue
    if (-not $command) {
        throw "Required command not found: $name"
    }
}

function Invoke-Git($arguments) {
    & git -C $projectDir @arguments
    if ($LASTEXITCODE -ne 0) {
        throw "Git command failed: git $($arguments -join ' ')"
    }
}

$projectDir = Split-Path -Parent $PSScriptRoot

Require-Command git

Write-Step "Project directory"
Write-Host $projectDir

Write-Step "Checking git repository"
Invoke-Git @("rev-parse", "--is-inside-work-tree") | Out-Null

$currentBranch = (& git -C $projectDir branch --show-current).Trim()
if ([string]::IsNullOrWhiteSpace($currentBranch)) {
    throw "Could not detect current git branch."
}

$statusLines = @(& git -C $projectDir status --short)
if ($LASTEXITCODE -ne 0) {
    throw "Failed to read git status."
}

if ($statusLines.Count -gt 0 -and -not $AllowDirty) {
    Write-Step "Working tree is not clean"
    $statusLines | ForEach-Object { Write-Host $_ -ForegroundColor Yellow }
    throw "Please commit or stash your local changes first, or rerun with -AllowDirty if you know what you are doing."
}

Write-Step "Fetching origin"
Invoke-Git @("fetch", "origin")

Write-Step "Pulling latest changes"
Invoke-Git @("pull", "--rebase", "origin", $currentBranch)

Write-Step "Done"
Write-Host "Your local branch is updated from origin/$currentBranch." -ForegroundColor Green
