param(
    [string]$Server = $env:ONEC_SQL_SERVER,
    [string]$Database = $env:ONEC_SQL_DATABASE,
    [string]$User = $env:ONEC_SQL_USER,
    [string]$Password = $env:ONEC_SQL_PASSWORD,
    [string]$OutputPath = $env:ONEC_SQL_EXPORT_PATH,
    [int]$CommandTimeoutSeconds = 0
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

if (-not $Server) { throw "Server is required. Use -Server or ONEC_SQL_SERVER." }
if (-not $Database) { throw "Database is required. Use -Database or ONEC_SQL_DATABASE." }
if (-not $User) { throw "User is required. Use -User or ONEC_SQL_USER." }
if (-not $Password) { throw "Password is required. Use -Password or ONEC_SQL_PASSWORD." }
if (-not $OutputPath) { throw "OutputPath is required. Use -OutputPath or ONEC_SQL_EXPORT_PATH." }

$resolvedOutput = [System.IO.Path]::GetFullPath($OutputPath)
$binaryOutput = Join-Path $resolvedOutput "binary"
New-Item -ItemType Directory -Force -Path $binaryOutput | Out-Null

function Convert-ToSafeName {
    param([string]$Value)
    if (-not $Value) { return "empty" }
    $safe = $Value -replace '[\\/:*?"<>|]', '_'
    if ($safe.Length -gt 80) { $safe = $safe.Substring(0, 80) }
    return $safe
}

$connectionString = "Server=$Server;Database=$Database;User ID=$User;Password=$Password;Encrypt=False;TrustServerCertificate=True;Application Name=Codex 1C SQL Extensions Export;"
$connection = [System.Data.SqlClient.SqlConnection]::new($connectionString)
$command = $connection.CreateCommand()
$command.CommandTimeout = $CommandTimeoutSeconds
$command.CommandText = "SELECT * FROM dbo.[_ExtensionsInfo] ORDER BY [_ExtName]"

$rows = @()

try {
    $connection.Open()
    $reader = $command.ExecuteReader()
    try {
        $rowIndex = 0
        while ($reader.Read()) {
            $rowIndex++
            $row = [ordered]@{
                row_index = $rowIndex
                columns = [ordered]@{}
            }

            $extName = ""
            for ($i = 0; $i -lt $reader.FieldCount; $i++) {
                if ($reader.GetName($i) -eq "_ExtName" -and -not $reader.IsDBNull($i)) {
                    $extName = [string]$reader.GetValue($i)
                    break
                }
            }
            $safeExtName = Convert-ToSafeName $extName

            for ($i = 0; $i -lt $reader.FieldCount; $i++) {
                $columnName = $reader.GetName($i)
                if ($reader.IsDBNull($i)) {
                    $row.columns[$columnName] = $null
                    continue
                }

                $value = $reader.GetValue($i)
                if ($value -is [byte[]]) {
                    $binaryName = "{0:D3}_{1}_{2}.bin" -f $rowIndex, $safeExtName, (Convert-ToSafeName $columnName)
                    $binaryPath = Join-Path $binaryOutput $binaryName
                    [System.IO.File]::WriteAllBytes($binaryPath, $value)
                    $row.columns[$columnName] = [ordered]@{
                        type = "binary"
                        bytes = $value.Length
                        path = $binaryPath
                    }
                    continue
                }

                $row.columns[$columnName] = $value
            }
            $rows += [pscustomobject]$row
        }
    }
    finally {
        if ($reader -ne $null) { $reader.Dispose() }
    }
}
finally {
    if ($connection -ne $null) { $connection.Dispose() }
}

$result = [pscustomobject]@{
    schema = "onec_sql_extensions_info_export.v1"
    table = "_ExtensionsInfo"
    output_path = $resolvedOutput
    row_count = $rows.Count
    rows = $rows
}

$jsonPath = Join-Path $resolvedOutput "extensions-info.json"
$result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$result | ConvertTo-Json -Depth 5
