param(
    [string]$CommitMessage = ""
)

$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."
}

Write-Step "Staging changes"
Invoke-Git @("add", ".")

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

if ($statusLines.Count -gt 0) {
    if ([string]::IsNullOrWhiteSpace($CommitMessage)) {
        $CommitMessage = Read-Host "Enter commit message"
    }
    if ([string]::IsNullOrWhiteSpace($CommitMessage)) {
        throw "Commit message is required when there are staged changes."
    }

    Write-Step "Creating commit"
    Write-Host $CommitMessage -ForegroundColor Green
    Invoke-Git @("commit", "-m", $CommitMessage)
}
else {
    Write-Step "No local changes to commit"
    Write-Host "Nothing new to commit. The script will still push the current branch." -ForegroundColor Yellow
}

Write-Step "Pushing to GitHub"
Invoke-Git @("push", "origin", $currentBranch)

Write-Step "Done"
Write-Host "Uploaded source code to origin/$currentBranch." -ForegroundColor Green
