[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string] $DatasetDir,
    [Parameter(Mandatory = $true)]
    [string] $OutputDir,
    [Parameter(Mandatory = $true)]
    [string] $PythonExe,
    [string] $CacheDir,
    [int] $BatchSize = 4,
    [int] $NumWorkers = 2,
    [int] $MaxEpochs = 2000,
    [switch] $SmokeTest
)

$ErrorActionPreference = 'Stop'

$dataset = [IO.Path]::GetFullPath($DatasetDir)
$output = [IO.Path]::GetFullPath($OutputDir)
$python = [IO.Path]::GetFullPath($PythonExe)
$metadata = Join-Path $dataset 'metadata.csv'
$audioDir = Join-Path $dataset 'wav'
$configPath = Join-Path $output 'aletheia_ru.onnx.json'
$cacheDir = if ($CacheDir) {
    [IO.Path]::GetFullPath($CacheDir)
} else {
    Join-Path $output 'cache'
}
$checkpointDir = Join-Path $output 'checkpoints'

if (-not (Test-Path -LiteralPath $python -PathType Leaf)) {
    throw "Python executable not found: $python"
}
if (-not (Test-Path -LiteralPath $metadata -PathType Leaf)) {
    throw "Piper metadata not found: $metadata"
}
if (-not (Test-Path -LiteralPath $audioDir -PathType Container)) {
    throw "Piper audio directory not found: $audioDir"
}

New-Item -ItemType Directory -Force -Path $output, $cacheDir, $checkpointDir | Out-Null

$fitArgs = @(
    '-m', 'piper.train', 'fit',
    '--data.voice_name', 'aletheia_ru',
    '--data.csv_path', $metadata,
    '--data.audio_dir', $audioDir,
    '--data.espeak_voice', 'ru',
    '--data.cache_dir', $cacheDir,
    '--data.config_path', $configPath,
    '--data.batch_size', $BatchSize,
    '--data.num_workers', $NumWorkers,
    '--model.sample_rate', '22050',
    '--trainer.accelerator', 'gpu',
    '--trainer.devices', '1',
    '--trainer.precision', '16-mixed',
    '--trainer.max_epochs', $MaxEpochs,
    '--trainer.default_root_dir', $checkpointDir
)

if ($SmokeTest) {
    $fitArgs += @('--trainer.fast_dev_run', 'true', '--trainer.num_sanity_val_steps', '0')
}

& $python @fitArgs
if ($LASTEXITCODE -ne 0) {
    throw "Piper training exited with code $LASTEXITCODE"
}

if ($SmokeTest) {
    Write-Output 'PIPER_CUDA_SMOKE_TEST_OK'
    exit 0
}

$checkpoint = Get-ChildItem -LiteralPath $checkpointDir -Filter '*.ckpt' -File -Recurse |
    Sort-Object LastWriteTimeUtc -Descending |
    Select-Object -First 1
if (-not $checkpoint) {
    throw "Training finished without a checkpoint under $checkpointDir"
}

$onnxPath = Join-Path $output 'aletheia_ru.onnx'
& $python -m piper.train.export_onnx --checkpoint $checkpoint.FullName --output-file $onnxPath
if ($LASTEXITCODE -ne 0) {
    throw "Piper ONNX export exited with code $LASTEXITCODE"
}

$artifacts = [ordered]@{}
foreach ($artifactPath in @($onnxPath, $configPath)) {
    if (-not (Test-Path -LiteralPath $artifactPath -PathType Leaf)) {
        throw "Expected artifact not found: $artifactPath"
    }
    $item = Get-Item -LiteralPath $artifactPath
    $artifacts[$item.Name] = [ordered]@{
        bytes = $item.Length
        sha256 = (Get-FileHash -LiteralPath $item.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
    }
}

$manifestPath = Join-Path $output 'artifacts.json'
$artifacts | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $manifestPath -Encoding utf8
$artifacts | ConvertTo-Json -Depth 4
