<#
.SYNOPSIS
  Register and collect from all SQL Server instances on this laptop for a Sovereign pilot.
.DESCRIPTION
  Auto-discovers instances from the SQL registry, optionally starts stopped SQL services,
  registers cloud catalog slots (AWS RDS / CloudWatch), and runs the collector on reachable instances.
  Config: scripts/pilot-instances.json
.EXAMPLE
  .\scripts\run-laptop-pilot.ps1
#>
[CmdletBinding()]
param(
    [string[]]$ServerList = @(),
    [switch]$NoAutoDiscover,
    [switch]$IncludeAzure,
    [string]$AzureServer = 'azuresqlclass.database.windows.net',
    [System.Management.Automation.PSCredential]$AzureCredential,
    [string]$SovereignApi = 'http://localhost:3041',
    [string]$PilotConfigPath,
    [switch]$KeepDemoSeed,
    [int]$LicenseInstances = 0
)

$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path $PSScriptRoot -Parent
$collector = Join-Path $repoRoot 'src\collectors\DBAOps-Sovereign-Collector.ps1'
. (Join-Path $PSScriptRoot 'Discover-SqlInstances.ps1')

if (-not $PilotConfigPath) {
    $PilotConfigPath = Join-Path $PSScriptRoot 'pilot-instances.json'
}
$config = Get-PilotInstanceConfig -ConfigPath $PilotConfigPath

$licenseCap = if ($LicenseInstances -gt 0) { $LicenseInstances } elseif ($config.licenseInstances) { [int]$config.licenseInstances } else { 10 }
$startStopped = if ($NoAutoDiscover) { $false } else { $config.startStoppedInstances -ne $false }
$removeDemo = (-not $KeepDemoSeed) -and ($config.removeDemoPlaceholder -ne $false)

function Invoke-SovereignRegister {
    param(
        [Parameter(Mandatory)][string]$ServerName,
        [string]$Engine = 'SQL Server',
        [string]$Version,
        [string]$Edition,
        [string]$Environment,
        [string]$BusinessUnit
    )
    $body = @{
        serverName   = $ServerName
        engine       = $Engine
        version      = $Version
        edition      = $Edition
        environment  = $Environment
        businessUnit = $BusinessUnit
    } | ConvertTo-Json -Compress
    try {
        Invoke-RestMethod -Method POST -Uri "$SovereignApi/api/fleet/register" -ContentType 'application/json' -Body $body | Out-Null
        Write-Host "  Registered $ServerName ($Engine)" -ForegroundColor Green
        return $true
    } catch {
        if ($_.Exception.Response.StatusCode.value__ -eq 409) {
            Write-Host "  Already registered: $ServerName" -ForegroundColor DarkYellow
            return $true
        }
        Write-Warning "  Register failed for ${ServerName}: $($_.Exception.Message)"
        return $false
    }
}

Write-Host '=== DBAOps Sovereign - Laptop pilot (all instances) ===' -ForegroundColor Cyan
Write-Host "API: $SovereignApi"

$health = Invoke-RestMethod -Uri "$SovereignApi/api/health" -TimeoutSec 8
Write-Host "API OK ($($health.version))"

$license = Invoke-RestMethod -Uri "$SovereignApi/api/license"
Write-Host "License: $($license.instancesUsed)/$($license.instancesAllowed) instances ($($license.status))"

if ($removeDemo) {
    Write-Host "Preparing fleet slots (license cap $licenseCap)..."
    $cleanup = @"
SET NOCOUNT ON;
UPDATE ctl.LicenseEntitlements SET InstancesAllowed = $licenseCap WHERE IsActive = 1;
DELETE FROM ctl.Servers WHERE ServerName IN (N'SQLPROD01', N'SQLPROD02', N'SQLDR01');
"@
    sqlcmd -S localhost -E -d SovereignRepository -Q $cleanup | Out-Null
}

$targets = [System.Collections.Generic.List[string]]::new()

if ($ServerList.Count -gt 0) {
    $targets.AddRange([string[]]$ServerList)
} elseif (-not $NoAutoDiscover) {
    Write-Host 'Auto-discovering local SQL instances from registry...'
    foreach ($d in Get-LocalSqlInstanceConnectNames) {
        if ($startStopped) {
            Start-SqlInstanceServiceIfStopped -ServiceName $d.ServiceName | Out-Null
        }
        $targets.Add($d.ConnectName)
    }
    foreach ($extra in @($config.extraLocalConnectNames)) {
        if ($extra) { $targets.Add([string]$extra) }
    }
} else {
    Write-Warning 'NoAutoDiscover set and no -ServerList — add servers to ctl.Servers or pass -ServerList.'
}

if ($IncludeAzure -or ($config.azureSql -and $config.azureSql.enabled)) {
    $AzureServer = if ($config.azureSql.serverName) { [string]$config.azureSql.serverName } else { $AzureServer }
    if ($AzureCredential) { $targets.Add($AzureServer) }
    else { Write-Warning 'Azure SQL enabled in config but -AzureCredential not supplied.' }
}

$reachable = @()
$canonicalByConnect = @{}
foreach ($srv in ($targets | Select-Object -Unique)) {
    Write-Host "Probing $srv..."
    $cred = if ($srv -eq $AzureServer) { $AzureCredential } else { $null }
    $canonical = Test-SqlInstanceReachable -ConnectName $srv -Credential $cred
    if ($canonical) {
        Write-Host "  Reachable -> $canonical" -ForegroundColor Green
        $reachable += $srv
        $canonicalByConnect[$srv] = $canonical
    } else {
        Write-Warning "  Skipping unreachable instance: $srv"
    }
}

Write-Host 'Registering SQL Server fleet instances...'
foreach ($srv in $reachable) {
    $cred = if ($srv -eq $AzureServer) { $AzureCredential } else { $null }
    $sqlArgs = @('-S', $srv, '-Q', "SELECT CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(64)), CAST(SERVERPROPERTY('Edition') AS NVARCHAR(128))", '-W', '-s', '|')
    if ($cred) {
        $net = $cred.GetNetworkCredential()
        $sqlArgs = @('-S', $srv, '-U', $net.UserName, '-P', $net.Password) + $sqlArgs[2..($sqlArgs.Length - 1)]
    } else {
        $sqlArgs = @('-S', $srv, '-E') + $sqlArgs[2..($sqlArgs.Length - 1)]
    }
    $info = (& sqlcmd @sqlArgs 2>&1 | Where-Object { $_ -match '\|' }) -split '\|'
    $canonical = $canonicalByConnect[$srv]
    if ($canonical) {
        $engine = if ($srv -eq $AzureServer) { 'Azure SQL' } else { 'SQL Server' }
        Invoke-SovereignRegister -ServerName $canonical -Version $info[0].Trim() -Edition $info[1].Trim() -Engine $engine | Out-Null
    }
}

if ($config -and $config.cloudInstances) {
    Write-Host 'Registering cloud catalog slots (AWS RDS / CloudWatch)...'
    foreach ($cloud in @($config.cloudInstances)) {
        $cName = [string]$cloud.serverName
        if (-not $cName.Trim()) { continue }
        Invoke-SovereignRegister -ServerName $cName -Engine ([string]$cloud.engine) -Environment ([string]$cloud.environment) -BusinessUnit ([string]$cloud.businessUnit) | Out-Null
    }
}

if ($reachable.Count -gt 0) {
    Write-Host 'Running collector on reachable instances...'
    $localServers = $reachable | Where-Object { $_ -ne $AzureServer }
    if ($localServers.Count -gt 0) {
        & $collector -ServerList $localServers -SovereignApi $SovereignApi -SubmitAll
    }
    $azureServers = $reachable | Where-Object { $_ -eq $AzureServer }
    if ($azureServers.Count -gt 0 -and $AzureCredential) {
        & $collector -ServerList $azureServers -SovereignApi $SovereignApi -SqlCredential $AzureCredential -SubmitAll
    }
}

$fleet = Invoke-RestMethod -Uri "$SovereignApi/api/fleet"
Write-Host ''
Write-Host '=== Pilot fleet enrollment complete ===' -ForegroundColor Cyan
Write-Host "Fleet count: $($fleet.Count)"
foreach ($s in $fleet) {
    Write-Host "  $($s.ServerName) [$($s.Engine)]"
}
Write-Host ''
Write-Host 'Dashboard: http://localhost:3000/fleet'
