modules/CheatLab.Core.ps1

# Core state and helpers for CheatLab CLI

if ($null -eq $global:CheatUsername) { $global:CheatUsername = "Dummy" }
if ($null -eq $global:CheatAuthKey) { $global:CheatAuthKey = "toerrishuman" }
if ($null -eq $global:CheatAiHistory) { $global:CheatAiHistory = @() }

if (-not $script:CheatLabBaseUrl) {
    $script:CheatLabBaseUrl = "https://cheatlab.onrender.com"
}

function file {
    param([string]$filename)

    try {
        if (-not (Test-Path $filename)) {
            Write-Error "File not found: $filename"
            return $null
        }

        return Get-Content -Path $filename -Raw
    }
    catch {
        Write-Error "Failed to read file: $($_.Exception.Message)"
        return $null
    }
}

function Build-Url {
    param([string]$base, [hashtable]$params)

    if ($global:CheatUsername -and $global:CheatAuthKey) {
        if (-not $params.username) { $params.username = $global:CheatUsername }
        if (-not $params.auth_key) { $params.auth_key = $global:CheatAuthKey }
    }

    $query = @()
    foreach ($k in $params.Keys) {
        $v = $params[$k]
        if ($null -ne $v -and $v -ne "" -and $v -ne $false) {
            $query += "$k=$([uri]::EscapeDataString($v.ToString()))"
        }
    }

    if ($query.Count -gt 0) {
        return "$base`?" + ($query -join "`&")
    }

    return $base
}

function Invoke-CheatApi {
    param($url, $method = "GET", $body = $null, $timeoutSec = 30)

    try {
        $params = @{ Uri = $url; Method = $method; TimeoutSec = $timeoutSec }
        if ($body) {
            $params.Body = ($body | ConvertTo-Json -Depth 10)
            $params.ContentType = "application/json"
        }

        $r = Invoke-RestMethod @params
        if ($r -is [string]) { Write-Output $r }
        else { $r | ConvertTo-Json -Depth 10 }
    }
    catch {
        if ($_.Exception.Message -match "timeout|timed out") {
            Write-Error "Request timed out after $timeoutSec seconds (database may be slow)"
            return
        }

        if ($_.Exception.Response) {
            try {
                $stream = $_.Exception.Response.GetResponseStream()
                $reader = New-Object System.IO.StreamReader($stream)
                $responseBody = $reader.ReadToEnd()
                $reader.Close()
                $stream.Close()

                if ($responseBody) {
                    Write-Error "Server error: $responseBody"
                }
                else {
                    Write-Error "Request failed: $($_.Exception.Message)"
                }
            }
            catch {
                Write-Error "Request failed: $($_.Exception.Message)"
            }
        }
        else {
            Write-Error "Request failed: $($_.Exception.Message)"
        }
    }
}

function Resolve-Endpoint {
    param($ep)

    if ($ep -match '^\d+$') { return "/$ep" }
    elseif ($ep -in @("latest", "uidata", "all", "ping")) { return "/$ep" }
    else { return "/key/$ep" }
}

function Set-CheatCredentials {
    param(
        [string]$Username,
        [string]$AuthKey
    )

    if ($Username -and $AuthKey) {
        $global:CheatUsername = $Username
        $global:CheatAuthKey = $AuthKey
        Write-Host "Credentials configured for user: $Username" -ForegroundColor Green
        Write-Host "You can now use cheat commands without specifying credentials" -ForegroundColor Gray
        return
    }

    if (-not $Username -and -not $AuthKey) {
        if ($global:CheatUsername) {
            Write-Host "Current user: $global:CheatUsername" -ForegroundColor Cyan
        }
        else {
            Write-Host "No credentials configured" -ForegroundColor Yellow
        }
        return
    }

    Write-Host "Error: Both username and auth_key are required" -ForegroundColor Red
}