[CmdletBinding()]
param(
  [string]$Ffmpeg = 'C:\ffmpeg_latest\ffmpeg.exe',
  [string]$Ffprobe = 'C:\ffmpeg_latest\ffprobe.exe',
  [string]$ProjectRoot = ''
)

$ErrorActionPreference = 'Stop'

if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
  $ProjectRoot = Split-Path -Parent $PSScriptRoot
}
. (Join-Path $ProjectRoot 'scripts/hash-utils.ps1')

if (-not (Test-Path -LiteralPath $Ffmpeg)) {
  throw "FFmpeg was not found at $Ffmpeg"
}
if (-not (Test-Path -LiteralPath $Ffprobe)) {
  throw "ffprobe was not found at $Ffprobe"
}

$reviewRoot = Join-Path $ProjectRoot 'build\lemon-review'
$captureRoot = Join-Path $reviewRoot 'captures'
$publicRoot = Join-Path $ProjectRoot 'website\public\demo'
$hero = Join-Path $ProjectRoot 'website\public\smartcut64-hero.png'
$sourceLoaded = Join-Path $captureRoot 'source-loaded.png'
$cutsApplied = Join-Path $captureRoot 'cuts-applied.png'
$previewEdits = Join-Path $captureRoot 'preview-edits.png'
$video = Join-Path $publicRoot 'smartcut64-overview.mp4'
$poster = Join-Path $publicRoot 'smartcut64-demo-poster.png'
$probeReport = Join-Path $reviewRoot 'smartcut64-overview.ffprobe.json'
$hashReport = Join-Path $reviewRoot 'smartcut64-overview.sha256.txt'
$filterScript = Join-Path $reviewRoot 'smartcut64-overview.filter'
$frameRoot = Join-Path $reviewRoot 'frames'

foreach ($required in @($hero, $sourceLoaded, $cutsApplied, $previewEdits)) {
  if (-not (Test-Path -LiteralPath $required)) {
    throw "Required demo image is missing: $required"
  }
}

New-Item -ItemType Directory -Force -Path $reviewRoot, $publicRoot, $frameRoot | Out-Null

Add-Type -AssemblyName System.Drawing

function New-DemoFrame {
  param(
    [Parameter(Mandatory)] [string]$Source,
    [Parameter(Mandatory)] [string]$Destination,
    [Parameter(Mandatory)] [ValidateSet('Hero', 'Interface')] [string]$Layout,
    [Parameter(Mandatory)] [string]$Title,
    [Parameter(Mandatory)] [string]$Subtitle,
    [string]$Detail = ''
  )

  $canvas = [System.Drawing.Bitmap]::new(1280, 720, [System.Drawing.Imaging.PixelFormat]::Format24bppRgb)
  $image = [System.Drawing.Image]::FromFile($Source)
  $graphics = [System.Drawing.Graphics]::FromImage($canvas)
  $titleFont = [System.Drawing.Font]::new('Segoe UI Semibold', 38, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Pixel)
  $subtitleFont = [System.Drawing.Font]::new('Segoe UI', 24, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Pixel)
  $detailFont = [System.Drawing.Font]::new('Segoe UI', 22, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Pixel)
  $white = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::White)
  $green = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(255, 74, 222, 128))
  $panel = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(232, 17, 24, 32))
  $background = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(255, 17, 24, 32))
  $centred = [System.Drawing.StringFormat]::new()
  $centred.Alignment = [System.Drawing.StringAlignment]::Center

  try {
    $graphics.Clear([System.Drawing.Color]::FromArgb(255, 17, 24, 32))
    $graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
    $graphics.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
    $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
    $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit

    if ($Layout -eq 'Hero') {
      $scale = [Math]::Min(1280.0 / $image.Width, 720.0 / $image.Height)
      $width = [int][Math]::Round($image.Width * $scale)
      $height = [int][Math]::Round($image.Height * $scale)
      $graphics.DrawImage($image, [int]((1280 - $width) / 2), [int]((720 - $height) / 2), $width, $height)

      $panelY = if ([string]::IsNullOrWhiteSpace($Detail)) { 590 } else { 545 }
      $graphics.FillRectangle($panel, 0, $panelY, 1280, 720 - $panelY)
      $titleY = if ([string]::IsNullOrWhiteSpace($Detail)) { 608 } else { 562 }
      $subtitleY = if ([string]::IsNullOrWhiteSpace($Detail)) { 664 } else { 621 }
      $graphics.DrawString($Title, $titleFont, $white, [System.Drawing.RectangleF]::new(0, $titleY, 1280, 52), $centred)
      $graphics.DrawString($Subtitle, $subtitleFont, $green, [System.Drawing.RectangleF]::new(0, $subtitleY, 1280, 38), $centred)
      if (-not [string]::IsNullOrWhiteSpace($Detail)) {
        $graphics.DrawString($Detail, $detailFont, $white, [System.Drawing.RectangleF]::new(0, 668, 1280, 36), $centred)
      }
    }
    else {
      $scale = [Math]::Min(1152.0 / $image.Width, 720.0 / $image.Height)
      $width = [int][Math]::Round($image.Width * $scale)
      $height = [int][Math]::Round($image.Height * $scale)
      $x = [int]((1280 - $width) / 2)
      $y = [int]((720 - $height) / 2)
      $graphics.DrawImage($image, $x, $y, $width, $height)
      $graphics.FillRectangle($panel, 64, 24, 900, 94)
      $graphics.DrawString($Title, $titleFont, $white, 92, 35)
      $graphics.DrawString($Subtitle, $subtitleFont, $green, 94, 82)
    }

    $canvas.Save($Destination, [System.Drawing.Imaging.ImageFormat]::Png)
  }
  finally {
    $centred.Dispose()
    $background.Dispose()
    $panel.Dispose()
    $green.Dispose()
    $white.Dispose()
    $detailFont.Dispose()
    $subtitleFont.Dispose()
    $titleFont.Dispose()
    $graphics.Dispose()
    $image.Dispose()
    $canvas.Dispose()
  }
}

$introFrame = Join-Path $frameRoot '01-intro.png'
$sourceFrame = Join-Path $frameRoot '02-source.png'
$cutsFrame = Join-Path $frameRoot '03-cuts.png'
$previewFrame = Join-Path $frameRoot '04-preview.png'
$closeFrame = Join-Path $frameRoot '05-close.png'

New-DemoFrame -Source $hero -Destination $introFrame -Layout Hero `
  -Title 'Frame-accurate smart rendering for Windows' `
  -Subtitle 'Real interface. Original synthetic media. No third-party footage.'
New-DemoFrame -Source $sourceLoaded -Destination $sourceFrame -Layout Interface `
  -Title '1  Open and navigate' `
  -Subtitle 'Frame thumbnails, decoded waveform and exact source positions'
New-DemoFrame -Source $cutsApplied -Destination $cutsFrame -Layout Interface `
  -Title '2  Mark precise cuts' `
  -Subtitle 'Green is kept. Red is removed. The cut list stays frame accurate.'
New-DemoFrame -Source $previewEdits -Destination $previewFrame -Layout Interface `
  -Title '3  Preview only the kept programme' `
  -Subtitle 'Preview Your Edits skips removed ranges before export'
New-DemoFrame -Source $hero -Destination $closeFrame -Layout Hero `
  -Title 'SmartCut64 Personal' `
  -Subtitle 'GBP 4.99 one-time founding offer - two computers - no subscription' `
  -Detail 'Full codec matrix, policies and support at the SmartCut64 website'

$filter = @'
[0:v]setsar=1,format=yuv420p[v0];
[1:v]setsar=1,format=yuv420p[v1];
[2:v]setsar=1,format=yuv420p[v2];
[3:v]setsar=1,format=yuv420p[v3];
[4:v]setsar=1,format=yuv420p[v4];
[v0][v1]xfade=transition=fade:duration=1:offset=8[x1];
[x1][v2]xfade=transition=fade:duration=1:offset=20[x2];
[x2][v3]xfade=transition=fade:duration=1:offset=33[x3];
[x3][v4]xfade=transition=fade:duration=1:offset=46[video]
'@

[System.IO.File]::WriteAllText(
  $filterScript,
  $filter,
  [System.Text.UTF8Encoding]::new($false)
)

$arguments = @(
  '-hide_banner', '-y',
  '-loop', '1', '-framerate', '30', '-t', '9', '-i', $introFrame,
  '-loop', '1', '-framerate', '30', '-t', '13', '-i', $sourceFrame,
  '-loop', '1', '-framerate', '30', '-t', '14', '-i', $cutsFrame,
  '-loop', '1', '-framerate', '30', '-t', '14', '-i', $previewFrame,
  '-loop', '1', '-framerate', '30', '-t', '14', '-i', $closeFrame,
  '-f', 'lavfi', '-t', '60', '-i', 'anullsrc=r=48000:cl=stereo',
  '-filter_complex_script', $filterScript,
  '-map', '[video]', '-map', '5:a:0',
  '-t', '60', '-r', '30',
  '-c:v', 'libx264', '-preset', 'slow', '-crf', '18', '-pix_fmt', 'yuv420p',
  '-c:a', 'aac', '-b:a', '128k',
  '-movflags', '+faststart',
  $video
)

& $Ffmpeg @arguments
if ($LASTEXITCODE -ne 0) {
  throw "Demo encoding failed with exit code $LASTEXITCODE"
}

& $Ffmpeg -hide_banner -y -ss 25 -i $video -frames:v 1 -update 1 $poster
if ($LASTEXITCODE -ne 0) {
  throw "Poster extraction failed with exit code $LASTEXITCODE"
}

$probeJson = & $Ffprobe -v error -show_format -show_streams -of json $video
if ($LASTEXITCODE -ne 0) {
  throw "Demo probing failed with exit code $LASTEXITCODE"
}
$probeJson | Set-Content -LiteralPath $probeReport -Encoding utf8

& $Ffmpeg -v error -i $video -f null NUL
if ($LASTEXITCODE -ne 0) {
  throw "Full demo decode validation failed with exit code $LASTEXITCODE"
}

$hash = (Get-SmartCutSha256 -LiteralPath $video).ToLowerInvariant()
"$hash  website/public/demo/smartcut64-overview.mp4" |
  Set-Content -LiteralPath $hashReport -Encoding ascii

[pscustomobject]@{
  Video = $video
  Poster = $poster
  Bytes = (Get-Item -LiteralPath $video).Length
  Sha256 = $hash
  ProbeReport = $probeReport
} | Format-List
