param(
    [Parameter(Mandatory = $true, Position = 0)]
    [ValidateSet(
        "info",
        "heroes",
        "hero",
        "set-level",
        "set-gold",
        "set-hp",
        "revive",
        "reset",
        'reset-buffs',
        "delete",
        "engine-status",
        "engine-combats",
        "ws-connections",
        "add-potions",
        "towns",
        "start-adventure",
        "teleport-town",
        "start-rest",
        "leave-town",
        "start-roadside-rest",
        "stop-adventure",
        "stop-rest",
        "time-pause",
        "time-resume"
    )]
    [string]$Command,

    [long]$HeroId,
    [int]$TownId,
    [int]$Level,
    [long]$Gold,
    [int]$HP,
    [int]$Limit = 20,
    [int]$Offset = 0,
    [int]$N,
    [string]$BaseUrl = $env:ADMIN_BASE_URL,
    [string]$Username = $env:ADMIN_BASIC_AUTH_USERNAME,
    [string]$Password = $env:ADMIN_BASIC_AUTH_PASSWORD
)

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

if ([string]::IsNullOrWhiteSpace($BaseUrl)) {
    $BaseUrl = "http://localhost:8080"
}

if ([string]::IsNullOrWhiteSpace($Username) -or [string]::IsNullOrWhiteSpace($Password)) {
    throw "Missing admin credentials. Set ADMIN_BASIC_AUTH_USERNAME and ADMIN_BASIC_AUTH_PASSWORD, or pass -Username and -Password."
}

function Require-Value {
    param(
        [string]$Name,
        [object]$Value
    )

    if ($null -eq $Value -or ($Value -is [string] -and [string]::IsNullOrWhiteSpace($Value))) {
        throw "Parameter -$Name is required for '$Command'."
    }
}

function Invoke-AdminRequest {
    param(
        [Parameter(Mandatory = $true)][string]$Method,
        [Parameter(Mandatory = $true)][string]$Path,
        [object]$Body = $null
    )

    $uri = "{0}{1}" -f $BaseUrl.TrimEnd("/"), $Path
    $pair = "{0}:{1}" -f $Username, $Password
    $encoded = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
    $headers = @{
        Authorization = "Basic $encoded"
        Accept        = "application/json"
    }

    $params = @{
        Method      = $Method
        Uri         = $uri
        Headers     = $headers
        ContentType = "application/json"
    }

    if ($null -ne $Body) {
        $params.Body = ($Body | ConvertTo-Json -Depth 8 -Compress)
    }

    Invoke-RestMethod @params
}

switch ($Command) {
    "info" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/info"
    }
    "heroes" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/heroes?limit=$Limit&offset=$Offset"
    }
    "hero" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/heroes/$HeroId"
    }
    "set-level" {
        Require-Value -Name "HeroId" -Value $HeroId
        Require-Value -Name "Level" -Value $Level
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/set-level" -Body @{ level = $Level }
    }
    "set-gold" {
        Require-Value -Name "HeroId" -Value $HeroId
        Require-Value -Name "Gold" -Value $Gold
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/set-gold" -Body @{ gold = $Gold }
    }
    "set-hp" {
        Require-Value -Name "HeroId" -Value $HeroId
        Require-Value -Name "HP" -Value $HP
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/set-hp" -Body @{ hp = $HP }
    }
    "revive" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/revive" -Body @{}
    }
    "reset" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/reset" -Body @{}
    }
    "reset-buffs" {
            Require-Value -Name "HeroId" -Value $HeroId
            $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/reset-buff-charges" -Body @{}
        }

    "add-potions" {
            Require-Value -Name "HeroId" -Value $HeroId
            Require-Value -Name "N" -Value $N
            $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/add-potions" -Body @{ potions = $N}
        }
    "delete" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "DELETE" -Path "/admin/heroes/$HeroId"
    }
    "engine-status" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/engine/status"
    }
    "engine-combats" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/engine/combats"
    }
    "ws-connections" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/ws/connections"
    }
    "towns" {
        $result = Invoke-AdminRequest -Method "GET" -Path "/admin/towns"
    }
    "start-adventure" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/start-adventure" -Body @{}
    }
    "teleport-town" {
        Require-Value -Name "HeroId" -Value $HeroId
        Require-Value -Name "TownId" -Value $TownId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/teleport-town" -Body @{ townId = $TownId }
    }
    "start-rest" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/start-rest" -Body @{}
    }
    "leave-town" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/leave-town" -Body @{}
    }
    "start-roadside-rest" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/start-roadside-rest" -Body @{}
    }
    "stop-adventure" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/stop-adventure" -Body @{}
    }
    "stop-rest" {
        Require-Value -Name "HeroId" -Value $HeroId
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/heroes/$HeroId/stop-rest" -Body @{}
    }
    "time-pause" {
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/time/pause" -Body @{}
    }
    "time-resume" {
        $result = Invoke-AdminRequest -Method "POST" -Path "/admin/time/resume" -Body @{}
    }
    default {
        throw "Unsupported command: $Command"
    }
}

$result | ConvertTo-Json -Depth 20
