# ============================================================================
# Dream Server Windows -- install report generator
# ============================================================================
# Part of: installers/windows/lib/
# Purpose: Build a shareable support bundle with compose + system diagnostics.
# Requires: ui.ps1, detection.ps1, and llm-endpoint.ps1 sourced first.
# ============================================================================

function Invoke-OptionalCommand {
    param(
        [string]$Command,
        [string[]]$CommandArgs = @(),
        [int]$MaxLines = 120
    )

    $result = @{
        ok        = $false
        exit_code = -1
        lines     = @()
    }

    try {
        $prevEAP = $ErrorActionPreference
        $ErrorActionPreference = "SilentlyContinue"
        $output = & $Command @CommandArgs 2>&1 | ForEach-Object { $_.ToString() }
        $exitCode = $LASTEXITCODE
        $ErrorActionPreference = $prevEAP

        $result.ok = ($exitCode -eq 0)
        $result.exit_code = $exitCode
        if ($output) {
            $result.lines = @($output | Select-Object -First $MaxLines)
        }
        return $result
    } catch {
        $result.lines = @("command failed to execute: $($_.Exception.Message)")
        return $result
    }
}

function Test-HttpEndpoint {
    param(
        [string]$Url,
        [int]$TimeoutSec = 3
    )

    $status = @{
        url = $Url
        ok = $false
        status_code = 0
        error = ""
    }

    try {
        $resp = Invoke-WebRequest -Uri $Url -TimeoutSec $TimeoutSec -UseBasicParsing -ErrorAction SilentlyContinue
        if ($resp) {
            $status.status_code = [int]$resp.StatusCode
            $status.ok = ($status.status_code -ge 200 -and $status.status_code -lt 400)
        }
    } catch {
        $status.error = $_.Exception.Message
    }

    return $status
}

function New-DreamInstallReport {
    param(
        [string]$InstallDir = $script:DS_INSTALL_DIR,
        [Parameter(Mandatory = $true)]
        [AllowEmptyCollection()]
        [string[]]$ComposeFlags
    )

    $gpu = Get-GpuInfo
    $computer = Get-CimInstance Win32_ComputerSystem
    $os = Get-CimInstance Win32_OperatingSystem
    $ramBytes = [int64]$computer.TotalPhysicalMemory

    $nativeBackend = "none"
    if (Get-Command Get-NativeInferenceBackend -ErrorAction SilentlyContinue) {
        $nativeBackend = Get-NativeInferenceBackend
    }
    $llmEndpoint = Get-WindowsLocalLlmEndpoint -InstallDir $InstallDir -GpuBackend $gpu.Backend -NativeBackend $nativeBackend

    $composeConfigArgs = @("compose") + $ComposeFlags + @("config")
    $composePsArgs = @("compose") + $ComposeFlags + @("ps", "-a")

    $report = [ordered]@{
        generated_at = (Get-Date).ToString("o")
        platform = [ordered]@{
            os_caption = $os.Caption
            os_version = $os.Version
            os_build = $os.BuildNumber
            computer_name = $env:COMPUTERNAME
            ram_gb = [Math]::Round($ramBytes / 1GB, 2)
        }
        gpu = [ordered]@{
            backend = $gpu.Backend
            name = $gpu.Name
            vram_mb = $gpu.VRAM
            memory_type = $gpu.MemoryType
            native_inference_backend = $nativeBackend
        }
        compose = [ordered]@{
            flags = @($ComposeFlags)
            docker_version = Invoke-OptionalCommand -Command "docker" -CommandArgs @("version") -MaxLines 40
            docker_info = Invoke-OptionalCommand -Command "docker" -CommandArgs @("info") -MaxLines 80
            compose_config = Invoke-OptionalCommand -Command "docker" -CommandArgs $composeConfigArgs
            compose_ps = Invoke-OptionalCommand -Command "docker" -CommandArgs $composePsArgs -MaxLines 80
        }
        health = [ordered]@{
            llm_api = Test-HttpEndpoint -Url $llmEndpoint.HealthUrl
            open_webui = Test-HttpEndpoint -Url "http://localhost:3000"
            dashboard = Test-HttpEndpoint -Url "http://localhost:3001"
            dashboard_api = Test-HttpEndpoint -Url "http://localhost:3002/health"
        }
    }

    return $report
}

function Write-DreamInstallReport {
    param(
        [Parameter(Mandatory = $true)]
        [string]$InstallDir,
        [Parameter(Mandatory = $true)]
        [AllowEmptyCollection()]
        [string[]]$ComposeFlags
    )

    $artifactsDir = Join-Path (Join-Path $InstallDir "artifacts") "windows-report"
    New-Item -ItemType Directory -Path $artifactsDir -Force | Out-Null

    $jsonPath = Join-Path $artifactsDir "report.json"
    $txtPath = Join-Path $artifactsDir "report.txt"

    $report = New-DreamInstallReport -InstallDir $InstallDir -ComposeFlags $ComposeFlags
    ($report | ConvertTo-Json -Depth 8) | Set-Content -Path $jsonPath -Encoding UTF8

    $lines = @()
    $lines += "Dream Server Windows Report"
    $lines += "Generated: $($report.generated_at)"
    $lines += ""
    $lines += "Privacy"
    $lines += "- docker compose config output (inside report.json) can include interpolated env values from .env -- API keys, tokens, or other secrets. Review and redact before sharing publicly."
    $lines += ""
    $lines += "Platform"
    $lines += "- OS: $($report.platform.os_caption) ($($report.platform.os_version), build $($report.platform.os_build))"
    $lines += "- Machine: $($report.platform.computer_name)"
    $lines += "- RAM: $($report.platform.ram_gb) GB"
    $lines += ""
    $lines += "GPU"
    $lines += "- Backend: $($report.gpu.backend)"
    $lines += "- Name: $($report.gpu.name)"
    $lines += "- VRAM: $($report.gpu.vram_mb) MB"
    $lines += "- Native inference backend: $($report.gpu.native_inference_backend)"
    $lines += ""
    $lines += "Compose"
    $lines += "- Flags: docker compose $($report.compose.flags -join ' ')"
    $lines += "- docker version exit: $($report.compose.docker_version.exit_code)"
    $lines += "- docker info exit: $($report.compose.docker_info.exit_code)"
    $lines += "- compose config exit: $($report.compose.compose_config.exit_code)"
    $lines += "- compose ps -a exit: $($report.compose.compose_ps.exit_code)"
    $lines += ""
    $lines += "Health"
    $lines += "- LLM API: $($report.health.llm_api.ok) (status $($report.health.llm_api.status_code))"
    $lines += "- Open WebUI: $($report.health.open_webui.ok) (status $($report.health.open_webui.status_code))"
    $lines += "- Dashboard: $($report.health.dashboard.ok) (status $($report.health.dashboard.status_code))"
    $lines += "- Dashboard API: $($report.health.dashboard_api.ok) (status $($report.health.dashboard_api.status_code))"
    $lines += ""
    $lines += "Raw command snippets are available in report.json."

    $lines | Set-Content -Path $txtPath -Encoding UTF8

    Write-Host ""
    Write-Chapter "INSTALL REPORT"
    Write-AISuccess "Report generated:"
    Write-AI "  JSON: $jsonPath"
    Write-AI "  Text: $txtPath"
    Write-AIWarn "compose config in report.json may contain secrets from .env -- review before sharing."
    Write-AI "Attach report.json when filing Windows install/runtime issues."

    return @{
        JsonPath = $jsonPath
        TextPath = $txtPath
    }
}
