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]$OutputRoot = "reports\1c-sql\saved-state-watch",
    [string]$PreviousReport = "",
    [string]$BaseMetadataDir = "reports\1c-sql\upo\structured-metadata-all-kinds",
    [string]$ExtensionGuidIndex = "reports\1c-sql\upo\xml-guid-index-extensions.json",
    [string]$ExtensionManifestSummary = "reports\1c-sql\upo\extension-manifest-xml-part-summary.json",
    [string]$ConfigCASAllDir = "reports\1c-sql\upo\ConfigCAS-all",
    [string]$Python = "python",
    [switch]$SkipMarkdown,
    [switch]$SkipDelta
)

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." }

$resolvedRoot = [System.IO.Path]::GetFullPath($OutputRoot)
New-Item -ItemType Directory -Force -Path $resolvedRoot | Out-Null

$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$runDir = Join-Path $resolvedRoot $stamp
New-Item -ItemType Directory -Force -Path $runDir | Out-Null

$manifestPath = Join-Path $runDir "saved-state-watch-run.json"
$manifestCheckPath = Join-Path $runDir "saved-state-watch-run-check.json"
$manifestMarkdownPath = Join-Path $runDir "saved-state-watch-run.md"
$reportPath = Join-Path $runDir "saved-state-object-report.json"
$deltaPath = Join-Path $runDir "saved-state-object-report-delta.json"

function Read-JsonFile {
    param([string]$Path)
    return Get-Content -LiteralPath $Path -Raw -Encoding UTF8 | ConvertFrom-Json
}

function Find-PreviousReport {
    param(
        [string]$Root,
        [string]$CurrentRunDir
    )
    $currentFull = [System.IO.Path]::GetFullPath($CurrentRunDir)
    $candidates = @(
        Get-ChildItem -LiteralPath $Root -Directory |
            Sort-Object Name -Descending |
            ForEach-Object {
                $candidate = Join-Path $_.FullName "saved-state-object-report.json"
                if ([System.IO.Path]::GetFullPath($_.FullName) -ne $currentFull -and (Test-Path -LiteralPath $candidate)) {
                    $candidate
                }
            }
    )
    if (($candidates | Measure-Object).Count -gt 0) {
        return [string]$candidates[0]
    }
    return ""
}

if (-not $PreviousReport) {
    $PreviousReport = Find-PreviousReport -Root $resolvedRoot -CurrentRunDir $runDir
} elseif ($PreviousReport) {
    $PreviousReport = [System.IO.Path]::GetFullPath($PreviousReport)
}

$buildArgs = @(
    "-NoProfile", "-ExecutionPolicy", "Bypass",
    "-File", "scripts\build_1c_saved_state_object_report.ps1",
    "-Server", $Server,
    "-Database", $Database,
    "-User", $User,
    "-Password", $Password,
    "-OutputDir", $runDir,
    "-BaseMetadataDir", $BaseMetadataDir,
    "-ExtensionGuidIndex", $ExtensionGuidIndex,
    "-ExtensionManifestSummary", $ExtensionManifestSummary,
    "-ConfigCASAllDir", $ConfigCASAllDir,
    "-Python", $Python
)
if ($SkipMarkdown) {
    $buildArgs += "-SkipMarkdown"
}

$buildJson = & powershell @buildArgs
if ($LASTEXITCODE -ne 0) {
    throw "Saved-state report build failed."
}
$report = ($buildJson | Out-String | ConvertFrom-Json)

$delta = $null
if (-not $SkipDelta -and $PreviousReport -and (Test-Path -LiteralPath $PreviousReport)) {
    $deltaJson = & $Python scripts\compare_1c_saved_state_object_reports.py `
        --before $PreviousReport `
        --after $reportPath `
        --output $deltaPath
    if ($LASTEXITCODE -ne 0) {
        throw "Saved-state report delta failed."
    }
    $delta = Read-JsonFile $deltaPath
}

$result = [pscustomobject]@{
    schema = "onec_saved_state_watch_once.v1"
    server = $Server
    database = $Database
    output_root = $resolvedRoot
    run_dir = $runDir
    previous_report = if ($PreviousReport) { $PreviousReport } else { $null }
    report = $reportPath
    markdown = $report.markdown
    check = $report.check
    manifest_check = $manifestCheckPath
    manifest_markdown = if ($SkipMarkdown) { $null } else { $manifestMarkdownPath }
    delta = if ($delta) { $deltaPath } else { $null }
    delta_markdown = if ($delta) { $delta.markdown } else { $null }
    delta_check = if ($delta) { $delta.check } else { $null }
    counts = [pscustomobject]@{
        object_changes = $report.counts.object_changes
        system_changes = $report.counts.system_changes
        delta_objects_added = if ($delta) { $delta.counts.objects_added } else { $null }
        delta_objects_removed = if ($delta) { $delta.counts.objects_removed } else { $null }
        delta_objects_changed = if ($delta) { $delta.counts.objects_changed } else { $null }
        delta_objects_unchanged = if ($delta) { $delta.counts.objects_unchanged } else { $null }
    }
    safety = [pscustomobject]@{
        read_only = $true
        sql_write_performed = $false
        secrets_in_report = $false
    }
}

$result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $manifestPath -Encoding UTF8

if (-not $SkipMarkdown) {
    & $Python scripts\render_1c_saved_state_watch_once_markdown.py `
        --manifest $manifestPath `
        --output $manifestMarkdownPath | Out-Null
    if ($LASTEXITCODE -ne 0) {
        throw "Saved-state watch Markdown rendering failed."
    }
}

& $Python scripts\check_1c_saved_state_watch_once.py `
    --manifest $manifestPath `
    --output $manifestCheckPath | Out-Null
if ($LASTEXITCODE -ne 0) {
    throw "Saved-state watch manifest check failed."
}

$result | ConvertTo-Json -Depth 12
