<#
  ChessPublisher local FIDE rating-list updater
  Downloads the official Standard, Rapid and Blitz ZIP files plus the official LEGACY combined TXT player directory (unrated players included) beside ChessPublisher.html.
  It needs only Windows PowerShell; no installation and no GitHub Actions are required.
#>

[CmdletBinding()]
param(
  [ValidateRange(1, 10)]
  [int]$RetryCount = 5,
  [ValidateRange(30, 900)]
  [int]$TimeoutSeconds = 240
)

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$fideFolder = Join-Path $scriptRoot 'fide'
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ChessPublisher-FIDE-Updater/1.0'

$downloads = @(
  @{ Name = 'Standard';         FileName = 'standard_rating_list.zip'; TextFileName = 'standard.txt'; Url = 'https://ratings.fide.com/download/standard_rating_list.zip' },
  @{ Name = 'Rapid';            FileName = 'rapid_rating_list.zip';    TextFileName = 'rapid.txt';    Url = 'https://ratings.fide.com/download/rapid_rating_list.zip' },
  @{ Name = 'Blitz';            FileName = 'blitz_rating_list.zip';    TextFileName = 'blitz.txt';    Url = 'https://ratings.fide.com/download/blitz_rating_list.zip' },
  @{ Name = 'Players LEGACY (all, incl. unrated)'; FileName = 'players_list_legacy.zip'; TextFileName = 'players_legacy.txt'; EntryPattern = '\.txt$'; Url = 'https://ratings.fide.com/download/players_list_legacy.zip' }
)

function Write-Status([string]$Message, [ConsoleColor]$Color = [ConsoleColor]::Gray) {
  Write-Host ("[{0}] {1}" -f (Get-Date -Format 'HH:mm:ss'), $Message) -ForegroundColor $Color
}

function Test-ZipFile([string]$Path) {
  if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $false }
  if ((Get-Item -LiteralPath $Path).Length -lt 1024) { return $false }

  try {
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    $zip = [System.IO.Compression.ZipFile]::OpenRead($Path)
    try { return $zip.Entries.Count -gt 0 }
    finally { $zip.Dispose() }
  } catch {
    return $false
  }
}

function Get-FideFile($Item) {
  $destination = Join-Path $fideFolder $Item.FileName
  $textDestination = Join-Path $fideFolder $Item.TextFileName
  $temporary = "$destination.part"

  for ($attempt = 1; $attempt -le $RetryCount; $attempt++) {
    try {
      Remove-Item -LiteralPath $temporary -Force -ErrorAction SilentlyContinue
      Write-Status ("{0}: downloading (attempt {1}/{2})..." -f $Item.Name, $attempt, $RetryCount) Cyan

      Invoke-WebRequest -Uri $Item.Url -OutFile $temporary -UseBasicParsing -TimeoutSec $TimeoutSeconds `
        -Headers @{ 'User-Agent' = $userAgent; 'Accept' = 'application/zip,application/octet-stream,*/*' }

      if (-not (Test-ZipFile $temporary)) {
        throw 'The downloaded file is empty or is not a valid ZIP archive.'
      }

      Move-Item -LiteralPath $temporary -Destination $destination -Force
      $zip = [System.IO.Compression.ZipFile]::OpenRead($destination)
      try {
        $entryPattern = if ($Item.EntryPattern) { [string]$Item.EntryPattern } else { '\.txt$' }
        $entry = @($zip.Entries | Where-Object { $_.Name -match $entryPattern } | Sort-Object Length -Descending | Select-Object -First 1)[0]
        if ($null -eq $entry) { throw 'The ZIP archive does not contain the expected FIDE data file.' }
        $textTemporary = "$textDestination.part"
        Remove-Item -LiteralPath $textTemporary -Force -ErrorAction SilentlyContinue
        [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $textTemporary, $true)
        Move-Item -LiteralPath $textTemporary -Destination $textDestination -Force
      } finally {
        $zip.Dispose()
      }
      $sizeMB = [math]::Round(((Get-Item -LiteralPath $destination).Length / 1MB), 1)
      Write-Status ("{0}: downloaded, extracted and saved in fide\ ({1} MB)." -f $Item.Name, $sizeMB) Green
      return $true
    } catch {
      Remove-Item -LiteralPath $temporary -Force -ErrorAction SilentlyContinue
      $reason = $_.Exception.Message
      if ($attempt -lt $RetryCount) {
        $wait = [math]::Min(60, 5 * [math]::Pow(2, $attempt - 1))
        Write-Status ("{0}: failed - {1}. Retrying in {2} seconds..." -f $Item.Name, $reason, $wait) Yellow
        Start-Sleep -Seconds $wait
      } else {
        Write-Status ("{0}: FAILED after {1} attempts - {2}" -f $Item.Name, $RetryCount, $reason) Red
      }
    }
  }
  return $false
}

Write-Host ''
Write-Host 'chess-publisher - Local FIDE updater (4 databases)' -ForegroundColor White -BackgroundColor DarkBlue
Write-Status "Folder: $fideFolder"
New-Item -ItemType Directory -Path $fideFolder -Force | Out-Null

$failed = @()
foreach ($item in $downloads) {
  if (-not (Get-FideFile $item)) { $failed += $item.Name }
}

Write-Host ''
if ($failed.Count -eq 0) {
  Write-Status 'Done 4/4: Standard, Rapid, Blitz and Players LEGACY (including unrated players) are up to date.' Green
  Write-Status 'You can now open chess-publisher through ChessPublisher.exe. Existing program data was not changed.' Green
  exit 0
}

Write-Status ("Finished with errors: {0}. Existing successful files were kept unchanged." -f ($failed -join ', ')) Red
Write-Status 'Check your internet connection and run Update-FIDE.bat again later.' Yellow
exit 1
