$ErrorActionPreference = 'Continue'
$ProgressPreference   = 'SilentlyContinue'

function Section($name) { "`n===== $name =====" }

# ---------- Resolve sqlcmd up front ----------
$sqlcmd = (Get-Command sqlcmd -ErrorAction SilentlyContinue).Source
if (-not $sqlcmd) {
    foreach ($p in @(
        'C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\sqlcmd.exe',
        'C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\sqlcmd.exe',
        'C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\sqlcmd.exe',
        'C:\Program Files\Microsoft SQL Server\150\Tools\Binn\SQLCMD.EXE',
        'C:\Program Files\Microsoft SQL Server\140\Tools\Binn\SQLCMD.EXE',
        'C:\Program Files\Microsoft SQL Server\130\Tools\Binn\SQLCMD.EXE'
    )) {
        if (Test-Path $p) { $sqlcmd = $p; break }
    }
}
"sqlcmd: $sqlcmd"

# ---------- TASK 1: AIMSQL ENUMERATION (READ-ONLY) ----------

Section 'STEP 1: Service + process state'
Get-Service 'MSSQL$AIMSQL','SQLAgent$AIMSQL' -ErrorAction SilentlyContinue | Format-Table Name,Status,StartType -AutoSize

$svcCim = Get-CimInstance Win32_Service -Filter "Name='MSSQL`$AIMSQL'" -ErrorAction SilentlyContinue
$aimsqlPid = $null
if ($svcCim) { $aimsqlPid = [int]$svcCim.ProcessId }
"MSSQL`$AIMSQL PID (live from CIM): $aimsqlPid"
"MSSQL`$AIMSQL StartName (service account): $($svcCim.StartName)"

if ($aimsqlPid) {
    Get-Process -Id $aimsqlPid -ErrorAction SilentlyContinue |
        Select-Object Id,StartTime,
            @{n='WSMB';e={[math]::Round($_.WorkingSet64/1MB,1)}},
            @{n='VMMB';e={[math]::Round($_.VirtualMemorySize64/1MB,1)}},
            @{n='PrivateMB';e={[math]::Round($_.PrivateMemorySize64/1MB,1)}},
            Handles,@{n='Threads';e={$_.Threads.Count}},CPU |
        Format-List
} else {
    "No live PID for MSSQL`$AIMSQL"
}

Section 'STEP 2: Listening port + active TCP connections to AIMSQL'
if ($aimsqlPid) {
    "--- State summary ---"
    Get-NetTCPConnection -OwningProcess $aimsqlPid -ErrorAction SilentlyContinue |
        Group-Object State | Select-Object Name,Count | Format-Table -AutoSize

    "--- Listening sockets ---"
    Get-NetTCPConnection -OwningProcess $aimsqlPid -State Listen -ErrorAction SilentlyContinue |
        Select-Object LocalAddress,LocalPort | Format-Table -AutoSize

    "--- Established connections (remote talking to AIMSQL) ---"
    $est = Get-NetTCPConnection -OwningProcess $aimsqlPid -State Established -ErrorAction SilentlyContinue
    if ($est) {
        $est | Select-Object RemoteAddress,RemotePort,LocalAddress,LocalPort,CreationTime |
            Sort-Object RemoteAddress | Format-Table -AutoSize

        "--- Reverse-resolve unique remote IPs ---"
        $est.RemoteAddress | Sort-Object -Unique | ForEach-Object {
            $ip = $_
            $name = $null
            try { $name = [System.Net.Dns]::GetHostEntry($ip).HostName } catch {}
            [PSCustomObject]@{ RemoteIP=$ip; HostName=$name }
        } | Format-Table -AutoSize
    } else {
        "(no established connections to AIMSQL right now)"
    }

    "--- UDP endpoints for this PID ---"
    Get-NetUDPEndpoint -OwningProcess $aimsqlPid -ErrorAction SilentlyContinue |
        Select-Object LocalAddress,LocalPort | Format-Table -AutoSize
} else {
    "No PID — skipping TCP enumeration"
}

Section 'STEP 3: Windows-auth sqlcmd to .\AIMSQL'
$loginOk = $false
if ($sqlcmd) {
    $verOut = & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT @@VERSION;" 2>&1
    $verOut
    "---"
    & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT @@SERVERNAME AS server_name, SERVERPROPERTY('InstanceName') AS instance, SERVERPROPERTY('Edition') AS edition, SERVERPROPERTY('ProductVersion') AS product_version, SERVERPROPERTY('Collation') AS collation;" 2>&1
    if ($LASTEXITCODE -eq 0 -and ($verOut -join "`n") -notmatch 'Login failed') { $loginOk = $true }
}
"loginOk=$loginOk"

Section 'STEP 4: Databases on AIMSQL (sys.databases + sys.master_files)'
if ($loginOk -and $sqlcmd) {
    "--- sys.databases ---"
    & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT name, database_id, state_desc, recovery_model_desc, create_date, compatibility_level FROM sys.databases ORDER BY database_id;" 2>&1

    "--- sys.master_files (user DBs only, database_id > 4) ---"
    & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT database_id, type_desc, name AS logical_name, physical_name, size*8/1024 AS size_mb FROM sys.master_files WHERE database_id > 4 ORDER BY database_id, type;" 2>&1
} else {
    "Skipped (login failed) — will rely on file-system fallback below"
}

Section 'STEP 4b: File-system DB enumeration (fallback / cross-check) — AIMSQL DATA dirs'
$aimReg = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\*\Setup' -ErrorAction SilentlyContinue |
          Where-Object { $_.PSChildName -match '^MSSQL\d+\.' } |
          ForEach-Object {
              $instKey = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$($_.PSChildName)"
              $instName = (Get-ItemProperty -Path $instKey -ErrorAction SilentlyContinue).Name
              [PSCustomObject]@{ Folder=$_.PSChildName; InstanceName=$instName; SqlDataRoot=$_.SqlDataRoot; SQLBinRoot=$_.SQLBinRoot }
          } | Where-Object { $_.InstanceName -eq 'AIMSQL' }
$aimReg | Format-Table -AutoSize -Wrap

$dataDirs = @()
$dataDirs += $aimReg | Where-Object { $_.SqlDataRoot } | ForEach-Object { Join-Path $_.SqlDataRoot 'MSSQL\DATA' }
$dataDirs += 'C:\Program Files\Microsoft SQL Server\MSSQL*.AIMSQL\MSSQL\DATA'
$dataDirs += 'C:\Program Files (x86)\Microsoft SQL Server\MSSQL*.AIMSQL\MSSQL\DATA'
$dataDirs += 'S:\*AIMSQL*\MSSQL\DATA'
$dataDirs = $dataDirs | Where-Object { $_ } | Select-Object -Unique
"--- DATA dir candidates ---"
$dataDirs

"--- .mdf / .ldf / .ndf under AIMSQL DATA dirs ---"
foreach ($dir in $dataDirs) {
    Get-ChildItem -Path $dir -Include *.mdf,*.ldf,*.ndf -Recurse -ErrorAction SilentlyContinue |
        Select-Object FullName,@{n='SizeMB';e={[math]::Round($_.Length/1MB,1)}},LastWriteTime |
        Format-Table -AutoSize
}

Section 'STEP 5: Active sessions on AIMSQL'
if ($loginOk -and $sqlcmd) {
    & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT s.session_id, s.login_name, s.host_name, s.program_name, s.client_interface_name, s.login_time, s.last_request_end_time, s.status, c.client_net_address FROM sys.dm_exec_sessions s LEFT JOIN sys.dm_exec_connections c ON s.session_id = c.session_id WHERE s.is_user_process = 1 ORDER BY s.login_time;" 2>&1
} else {
    "Skipped (login failed)"
}

Section 'STEP 6: AIMSQL ERRORLOG location + tail'
$el = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server\','C:\Program Files (x86)\Microsoft SQL Server\','S:\','D:\','E:\' -Recurse -Filter ERRORLOG -ErrorAction SilentlyContinue |
      Where-Object { $_.FullName -like '*AIMSQL*MSSQL\Log\ERRORLOG' -and $_.FullName -notlike '*SQLEXPRESS*' } |
      Select-Object -First 5
$el | Select-Object FullName,LastWriteTime,Length | Format-Table -AutoSize

$primary = $el | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($primary) {
    "--- ERRORLOG path: $($primary.FullName) (LastWriteTime: $($primary.LastWriteTime)) ---"
    "--- Tail 200 lines ---"
    Get-Content $primary.FullName -Tail 200 -ErrorAction SilentlyContinue
} else {
    "No AIMSQL ERRORLOG located"
}

Section 'STEP 7: Memory cap (sp_configure read-only)'
if ($loginOk -and $sqlcmd) {
    & $sqlcmd -S '.\AIMSQL' -E -d master -h-1 -W -l 5 -Q "SET NOCOUNT ON; SELECT name, value, value_in_use, minimum, maximum FROM sys.configurations WHERE name IN ('max server memory (MB)','min server memory (MB)','show advanced options') ORDER BY name;" 2>&1
} else {
    "Skipped (login failed)"
}

Section 'STEP 8: Sanity — AIMSQL backup folders + .bak files'
"--- AIMSQL-named directories ---"
Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server\','S:\','E:\' -Recurse -Filter '*AIMSQL*' -Directory -ErrorAction SilentlyContinue |
    Select-Object FullName | Format-Table -AutoSize -Wrap

"--- .bak files under AIMSQL Backup dirs ---"
$bakRoots = @(
    'C:\Program Files\Microsoft SQL Server\MSSQL*.AIMSQL\MSSQL\Backup',
    'S:\*AIMSQL*\MSSQL\Backup',
    'S:\Backup',
    'S:\Backups'
)
foreach ($r in $bakRoots) {
    Get-ChildItem -Path $r -Filter '*.bak' -Recurse -ErrorAction SilentlyContinue |
        Select-Object FullName,@{n='SizeMB';e={[math]::Round($_.Length/1MB,1)}},LastWriteTime |
        Format-Table -AutoSize
}

# ---------- TASK 2: UNREGISTER SCHEDULED TASK (AUTHORIZED CHANGE) ----------

Section 'TASK 2: Unregister AIMSQL_Restart_20260506_0230 scheduled task'
$task = Get-ScheduledTask -TaskName 'AIMSQL_Restart_20260506_0230' -ErrorAction SilentlyContinue
if ($task) {
    $info = $task | Get-ScheduledTaskInfo
    "Found task — last run: $($info.LastRunTime), result: $($info.LastTaskResult), next run: $($info.NextRunTime)"
    try {
        Unregister-ScheduledTask -TaskName 'AIMSQL_Restart_20260506_0230' -Confirm:$false -ErrorAction Stop
        "Unregistered successfully."
    } catch {
        "Unregister FAILED: $_"
    }
    "--- Confirm gone ---"
    $check = Get-ScheduledTask -TaskName 'AIMSQL_Restart_20260506_0230' -ErrorAction SilentlyContinue
    if ($check) {
        "STILL PRESENT (failure)"
    } else {
        "Confirmed: task no longer registered."
    }
} else {
    "Task not found — already removed?"
}

Section 'TASK 2b: Audit-trail artifacts (do NOT delete)'
"--- aimsql-restart.ps1 ---"
$ps = Get-Item C:\Windows\Temp\aimsql-restart.ps1 -ErrorAction SilentlyContinue
if ($ps) { $ps | Select-Object FullName, Length, LastWriteTime | Format-List } else { "MISSING C:\Windows\Temp\aimsql-restart.ps1" }
"--- aimsql-restart.log ---"
$lg = Get-Item C:\Windows\Temp\aimsql-restart.log -ErrorAction SilentlyContinue
if ($lg) { $lg | Select-Object FullName, Length, LastWriteTime | Format-List } else { "MISSING C:\Windows\Temp\aimsql-restart.log" }

Section 'DONE'
"Completed at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz')"
