param(
    [Parameter(Mandatory = $true)][string]$ProviderName,
    [Parameter(Mandatory = $true)][string]$PromptFile,
    [Parameter(Mandatory = $true)][string]$OutputFile,
    [string]$WorkingDirectory = "",
    [string[]]$AddDirectories = @(),
    [ValidateSet("json", "text")][string]$OutputFormat = "json"
)

. (Join-Path $PSScriptRoot "Common.ps1")

if ([string]::IsNullOrWhiteSpace($WorkingDirectory)) {
    $WorkingDirectory = Get-RepoRoot
}

$provider = Get-ProviderConfig -Name $ProviderName
$runner = [string]$provider.runner
$promptText = Get-Content -Raw -Path $PromptFile
Ensure-Directory -Path (Split-Path -Parent $OutputFile)

if ($runner -eq "opencode") {
    $opencodeCommand = Get-Command opencode -ErrorAction SilentlyContinue
    if ($null -eq $opencodeCommand) {
        throw "opencode executable not found in PATH."
    }

    $arguments = @(
        "run",
        "--dir", $WorkingDirectory,
        "--model", [string]$provider.model,
        "--format", "json"
    )
    $agentProp = $provider.PSObject.Properties["agent"]
    if ($null -ne $agentProp -and -not [string]::IsNullOrWhiteSpace([string]$agentProp.Value)) {
        $arguments += @("--agent", [string]$agentProp.Value)
    }
    $variantProp = $provider.PSObject.Properties["variant"]
    if ($null -ne $variantProp -and -not [string]::IsNullOrWhiteSpace([string]$variantProp.Value)) {
        $arguments += @("--variant", [string]$variantProp.Value)
    }
    $arguments += @($promptText)

    $output = @(& $opencodeCommand.Source @arguments 2>&1)
    $exitCode = $LASTEXITCODE

    $result = [ordered]@{
        provider = $ProviderName
        runner = "opencode"
        model = [string]$provider.model
        working_directory = $WorkingDirectory
        prompt_file = $PromptFile
        output_format = "json"
        timestamp = (Get-Date).ToString("o")
        exit_code = $exitCode
        output = ($output -join [Environment]::NewLine)
    }

    Write-Utf8File -Path $OutputFile -Content (($result | ConvertTo-Json -Depth 100) + "`n")

    if ($exitCode -ne 0) {
        throw "Provider '$ProviderName' failed with exit code $exitCode. See $OutputFile"
    }
    return
}

$envNames = @(
    "ANTHROPIC_BASE_URL",
    "ANTHROPIC_AUTH_TOKEN",
    "API_TIMEOUT_MS",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
    "ANTHROPIC_MODEL",
    "ANTHROPIC_SMALL_FAST_MODEL",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL",
    "ANTHROPIC_DEFAULT_SONNET_MODEL",
    "ANTHROPIC_DEFAULT_OPUS_MODEL",
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS"
)

$previous = @{}
foreach ($name in $envNames) {
    $previous[$name] = [Environment]::GetEnvironmentVariable($name, "Process")
}

try {
    [Environment]::SetEnvironmentVariable("ANTHROPIC_BASE_URL", [string]$provider.base_url, "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_AUTH_TOKEN", [string]$provider.auth_token, "Process")
    [Environment]::SetEnvironmentVariable("API_TIMEOUT_MS", [string]$provider.timeout_ms, "Process")
    [Environment]::SetEnvironmentVariable("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", "1", "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_MODEL", [string]$provider.model, "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_SMALL_FAST_MODEL", [string]$provider.model, "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_DEFAULT_HAIKU_MODEL", [string]$provider.model, "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_DEFAULT_SONNET_MODEL", [string]$provider.model, "Process")
    [Environment]::SetEnvironmentVariable("ANTHROPIC_DEFAULT_OPUS_MODEL", [string]$provider.model, "Process")
    [Environment]::SetEnvironmentVariable(
        "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS",
        $(if ($provider.experimental_agent_teams) { "1" } else { "0" }),
        "Process"
    )

    $claudeArgs = @(
        "-p",
        "--output-format", $OutputFormat,
        "--dangerously-skip-permissions",
        "--model", [string]$provider.model
    )

    foreach ($path in @($WorkingDirectory) + $AddDirectories) {
        if (-not [string]::IsNullOrWhiteSpace($path)) {
            $claudeArgs += @("--add-dir", $path)
        }
    }

    $output = $promptText | & claude @claudeArgs "-" 2>&1
    $exitCode = $LASTEXITCODE
}
finally {
    foreach ($name in $envNames) {
        [Environment]::SetEnvironmentVariable($name, $previous[$name], "Process")
    }
}

$result = [ordered]@{
    provider = $ProviderName
    model = [string]$provider.model
    working_directory = $WorkingDirectory
    prompt_file = $PromptFile
    output_format = $OutputFormat
    timestamp = (Get-Date).ToString("o")
    exit_code = $exitCode
    output = ($output -join [Environment]::NewLine)
}

Write-Utf8File -Path $OutputFile -Content (($result | ConvertTo-Json -Depth 100) + "`n")

if ($exitCode -ne 0) {
    throw "Provider '$ProviderName' failed with exit code $exitCode. See $OutputFile"
}
