param(
    [string]$ProviderName,
    [string]$Endpoint,
    [string]$Model,
    [string]$ApiKey,
    [switch]$NoApiKey,
    [switch]$NonInteractive,
    [switch]$SkipPythonBootstrap
)

$ErrorActionPreference = "Stop"
$BaseDir = Split-Path (Split-Path -Parent $MyInvocation.MyCommand.Path) -Parent
$ConfigDir = Join-Path $BaseDir "Config"
$KeyDir = Join-Path $ConfigDir "Keys"
$MemoryDir = Join-Path $BaseDir "Memory"
$LogsDir = Join-Path $BaseDir "Logs"
$StateDir = Join-Path $BaseDir "State"
$OutputDir = Join-Path $BaseDir "Outputs"
$WorkspaceDir = Join-Path $BaseDir "Workspace"
$DeliverablesDir = Join-Path $BaseDir "Deliverables"
$ToolsDir = Join-Path $BaseDir "Tools"
$PortablePythonDir = Join-Path $ToolsDir "Python"
$PortablePythonExe = Join-Path $PortablePythonDir "python.exe"
$PythonInstallerDir = Join-Path $BaseDir "Installers\Python"
$PythonRuntimeConfig = Join-Path $ConfigDir "python_runtime.json"
$MailboxDirs = @("Mailbox", "Mailbox\Inbox", "Mailbox\InProgress", "Mailbox\Done", "Mailbox\Blocked", "Mailbox\Archive")

foreach ($dir in @($ConfigDir, $KeyDir, $MemoryDir, $LogsDir, $StateDir, $OutputDir, $WorkspaceDir, $DeliverablesDir, $ToolsDir, $PythonInstallerDir) + ($MailboxDirs | ForEach-Object { Join-Path $BaseDir $_ })) {
    if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
}

function Write-PortableText([string]$Path, [string]$Value) {
    $Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
    [System.IO.File]::WriteAllText($Path, $Value, $Utf8NoBom)
}
function Normalize-Endpoint([string]$Value) {
    if ([string]::IsNullOrWhiteSpace($Value)) { return $Value }
    $V = $Value.Trim()
    if ($V -match '/v1/?$') { return ($V.TrimEnd('/') + '/chat/completions') }
    return $V
}
function Safe-ProviderName([string]$Name) { return (($Name -replace '[^A-Za-z0-9_.-]', '_').Trim('_')) }
function Test-PythonExe([string]$Exe, [string]$ArgsPrefix) {
    try {
        $psi = New-Object System.Diagnostics.ProcessStartInfo
        $psi.FileName = $Exe
        $psi.Arguments = ($ArgsPrefix + " -c ""import sys; print(sys.version_info[0]); print(sys.executable)""").Trim()
        $psi.RedirectStandardOutput = $true
        $psi.RedirectStandardError = $true
        $psi.UseShellExecute = $false
        $psi.CreateNoWindow = $true
        $p = [System.Diagnostics.Process]::Start($psi)
        $p.WaitForExit(10000) | Out-Null
        $out = $p.StandardOutput.ReadToEnd()
        if ($p.ExitCode -eq 0 -and $out -match '^3') { return $true }
    } catch { }
    return $false
}
function Find-PythonRuntime {
    if (Test-Path $PortablePythonExe) { if (Test-PythonExe $PortablePythonExe "") { return @{ kind="portable"; command=$PortablePythonExe; args="" } } }
    if (Test-PythonExe "py.exe" "-3") { return @{ kind="py-launcher"; command="py.exe"; args="-3" } }
    if (Test-PythonExe "python.exe" "") { return @{ kind="path"; command="python.exe"; args="" } }
    return $null
}
function Install-PortablePythonIfNeeded {
    if ($SkipPythonBootstrap) { return Find-PythonRuntime }
    $Runtime = Find-PythonRuntime
    if ($Runtime) { return $Runtime }
    $Zip = Get-ChildItem -Path $PythonInstallerDir -Filter "python-*-embed-amd64.zip" -File -ErrorAction SilentlyContinue | Select-Object -First 1
    if (-not $Zip) { $Zip = Get-ChildItem -Path $PythonInstallerDir -Filter "*.zip" -File -ErrorAction SilentlyContinue | Select-Object -First 1 }
    if ($Zip) {
        Write-Host "[PYTHON] No system Python found. Extracting portable Python from $($Zip.Name)..." -ForegroundColor Yellow
        if (Test-Path $PortablePythonDir) { Remove-Item -Path $PortablePythonDir -Recurse -Force }
        New-Item -ItemType Directory -Path $PortablePythonDir -Force | Out-Null
        Expand-Archive -Path $Zip.FullName -DestinationPath $PortablePythonDir -Force
        $Runtime = Find-PythonRuntime
        if ($Runtime) { return $Runtime }
        Write-Host "[WARNING] Portable Python zip extracted, but python.exe did not self-test." -ForegroundColor Yellow
    }
    return $null
}

$PythonRuntime = Install-PortablePythonIfNeeded
if ($PythonRuntime) {
    Write-Host "[PYTHON] Runtime detected: $($PythonRuntime.kind) -> $($PythonRuntime.command) $($PythonRuntime.args)" -ForegroundColor Green
    $RuntimeCommandForConfig = $PythonRuntime.command
    if ($PythonRuntime.kind -eq "portable") { $RuntimeCommandForConfig = "Tools\Python\python.exe" }
    Write-PortableText -Path $PythonRuntimeConfig -Value ((@{ kind=$PythonRuntime.kind; command=$RuntimeCommandForConfig; args=$PythonRuntime.args; checkedAtUtc=(Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") } | ConvertTo-Json -Depth 4) + "`n")
} else {
    Write-Host "[PYTHON] No Python runtime found and no portable installer zip is available under Installers\Python." -ForegroundColor Yellow
    Write-Host "[PYTHON] Continuing in PowerShell-only mode. Use Start Start AgentOS.bat or Start Start AgentOS.bat." -ForegroundColor Yellow
    Write-PortableText -Path $PythonRuntimeConfig -Value ((@{ kind="missing"; command=""; args=""; checkedAtUtc=(Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); remediation="Install Python 3, enable py launcher, add python.exe to PATH, or include Installers/Python/python-*-embed-amd64.zip." } | ConvertTo-Json -Depth 4) + "`n")
}

if ([string]::IsNullOrWhiteSpace($ProviderName)) {
    if ($NonInteractive) { $ProviderName = "default" } else { $ProviderName = Read-Host "Provider profile name (example: ollama-cloud, local-ollama, openrouter)" }
}
if ([string]::IsNullOrWhiteSpace($ProviderName)) { $ProviderName = "default" }
$ProviderName = Safe-ProviderName $ProviderName

if ([string]::IsNullOrWhiteSpace($Endpoint)) {
    if ($NonInteractive) { throw "Endpoint is required in -NonInteractive mode." }
    $Endpoint = Read-Host "Chat completions endpoint URL (example: https://ollama.com/v1/chat/completions; /v1 will be normalized)"
}
if ([string]::IsNullOrWhiteSpace($Model)) {
    if ($NonInteractive) { throw "Model is required in -NonInteractive mode." }
    $Model = Read-Host "Default model id"
}
if (-not $NoApiKey -and [string]::IsNullOrWhiteSpace($ApiKey)) {
    if ($NonInteractive) { $ApiKey = "" } else {
        $SecureKey = Read-Host "API key (leave blank for local endpoints with no Authorization header)" -AsSecureString
        $Ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureKey)
        try { $ApiKey = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($Ptr) }
        finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($Ptr) }
    }
}

$Endpoint = Normalize-Endpoint $Endpoint
$Model = $Model.Trim()
if ([string]::IsNullOrWhiteSpace($Endpoint) -or [string]::IsNullOrWhiteSpace($Model)) { throw "Endpoint and model must be non-empty." }
if ($null -eq $ApiKey) { $ApiKey = "" }
$ApiKey = $ApiKey.Trim()
$KeyRel = "Config\Keys\$ProviderName.key.txt"
$KeyPath = Join-Path $BaseDir $KeyRel
Write-PortableText -Path $KeyPath -Value ($ApiKey + "`n")

$Provider = [ordered]@{
    endpoint = $Endpoint
    model = $Model
    apiKey = ""
    apiKeySet = (-not [string]::IsNullOrWhiteSpace($ApiKey))
    keyFile = $KeyRel
    activeProvider = $ProviderName
    installedAtUtc = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
}
Write-PortableText -Path (Join-Path $ConfigDir "provider.json") -Value (($Provider | ConvertTo-Json -Depth 8) + "`n")

$ProvidersPath = Join-Path $ConfigDir "providers.json"
$ProviderSet = $null
if (Test-Path $ProvidersPath) { try { $ProviderSet = Get-Content $ProvidersPath -Raw | ConvertFrom-Json } catch { $ProviderSet = $null } }
if ($null -eq $ProviderSet) { $ProviderSet = [pscustomobject]@{ activeProvider = $ProviderName; providers = [pscustomobject]@{} } }
if ($null -eq $ProviderSet.providers) { $ProviderSet | Add-Member -NotePropertyName providers -NotePropertyValue ([pscustomobject]@{}) -Force }
$ProviderSet.activeProvider = $ProviderName
$Entry = [ordered]@{ endpoint = $Endpoint; model = $Model; keyFile = $KeyRel; apiKeySet = (-not [string]::IsNullOrWhiteSpace($ApiKey)); type = "openai-compatible" }
$ProviderSet.providers | Add-Member -NotePropertyName $ProviderName -NotePropertyValue $Entry -Force
Write-PortableText -Path $ProvidersPath -Value (($ProviderSet | ConvertTo-Json -Depth 10) + "`n")

$State = @{ current_project = "Generic Agent Harness"; current_goal = "Installed and awaiting input"; timestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") } | ConvertTo-Json
Write-PortableText -Path (Join-Path $ConfigDir "active_state.json") -Value ($State + "`n")
if (!(Test-Path (Join-Path $BaseDir "Mailbox\Shared_Memory.json"))) { Write-PortableText -Path (Join-Path $BaseDir "Mailbox\Shared_Memory.json") -Value "{}`n" }
if (!(Test-Path (Join-Path $ConfigDir "subagent_pids.json"))) { Write-PortableText -Path (Join-Path $ConfigDir "subagent_pids.json") -Value "{}`n" }

Write-Host "[OK] Mix of Agents configured." -ForegroundColor Green
Write-Host "Provider: $ProviderName"
Write-Host "Endpoint: $Endpoint"
Write-Host "Model: $Model"
Write-Host "Key file: $KeyRel"
if ($PythonRuntime) { Write-Host "Python runtime: $($PythonRuntime.kind)" } else { Write-Host "Python runtime: missing (PowerShell runtime still available)" }
Write-Host "Launch options: Start Start AgentOS.bat, Start Start AgentOS.bat, Start Start AgentOS.bat, Start Start AgentOSP.bat, Start Start AgentOS.bat"
