param(
    [string]$ModsPath = ""
)

$ErrorActionPreference = "Stop"

$modName = "FS25_Mine"
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$projectZip = Join-Path $projectRoot "$modName.zip"
$tempZip = Join-Path ([System.IO.Path]::GetTempPath()) "$modName-build.zip"

function Format-ProductionAmount {
    param(
        [double]$Amount,
        [string]$CultureName
    )

    $culture = [System.Globalization.CultureInfo]::GetCultureInfo($CultureName)
    $roundedAmount = [Math]::Round($Amount)

    if ([Math]::Abs($Amount - $roundedAmount) -lt 0.0001) {
        return ([int64]$roundedAmount).ToString("N0", $culture)
    }

    return $Amount.ToString("N1", $culture)
}

function Set-L10nText {
    param(
        [xml]$ModDesc,
        [string]$Name,
        [string]$EnglishText,
        [string]$GermanText
    )

    $textNode = $ModDesc.SelectSingleNode("/modDesc/l10n/text[@name='$Name']")
    if ($null -eq $textNode) {
        throw "l10n Eintrag fehlt: $Name"
    }

    $englishNode = $textNode.SelectSingleNode("en")
    $germanNode = $textNode.SelectSingleNode("de")

    if ($null -eq $englishNode -or $null -eq $germanNode) {
        throw "l10n Eintrag ist unvollstaendig: $Name"
    }

    $englishNode.InnerText = $EnglishText
    $germanNode.InnerText = $GermanText
}

function Update-ProductionDescriptions {
    param(
        [string]$ProjectRoot
    )

    $modDescPath = Join-Path $ProjectRoot "modDesc.xml"

    $products = @{
        "PAYDIRT" = @{ En = "paydirt"; De = "Paydirt" }
        "STONE" = @{ En = "stone"; De = "Stein" }
        "DIRT" = @{ En = "dirt"; De = "Erde" }
        "MININGCOAL" = @{ En = "mining coal"; De = "Bergbau-Kohle" }
        "IRONORE" = @{ En = "iron ore"; De = "Eisenerz" }
        "SILVERORE" = @{ En = "silver ore"; De = "Silbererz" }
    }

    $productionItems = @(
        @{ XmlPath = "placeables\mine\mine.xml"; L10nName = "storeItem_paydirtMine_function" },
        @{ XmlPath = "placeables\stoneQuarry\stoneQuarry.xml"; L10nName = "storeItem_stoneQuarry_function" },
        @{ XmlPath = "placeables\dirt\dirt.xml"; L10nName = "storeItem_dirtPit_function" },
        @{ XmlPath = "placeables\coalmine\coalmine.xml"; L10nName = "storeItem_coalMine_function" },
        @{ XmlPath = "placeables\ironore\iron.xml"; L10nName = "storeItem_ironMine_function" },
        @{ XmlPath = "placeables\silverore\silver.xml"; L10nName = "storeItem_silverMine_function" }
    )

    $modDesc = New-Object System.Xml.XmlDocument
    $modDesc.PreserveWhitespace = $true
    $modDesc.Load($modDescPath)

    foreach ($item in $productionItems) {
        $placeablePath = Join-Path $ProjectRoot $item.XmlPath

        $placeable = New-Object System.Xml.XmlDocument
        $placeable.PreserveWhitespace = $true
        $placeable.Load($placeablePath)

        $productionNode = $placeable.SelectSingleNode("/placeable/produktion")
        if ($null -eq $productionNode) {
            throw "produktion Eintrag fehlt: $($item.XmlPath)"
        }

        $fillType = $productionNode.GetAttribute("fillType")
        $amountText = $productionNode.GetAttribute("amountPerHour")

        if ([string]::IsNullOrWhiteSpace($fillType) -or [string]::IsNullOrWhiteSpace($amountText)) {
            throw "produktion Eintrag ist unvollstaendig: $($item.XmlPath)"
        }

        $amountPerHour = [double]::Parse($amountText, [System.Globalization.CultureInfo]::InvariantCulture)

        if ($products.ContainsKey($fillType)) {
            $product = $products[$fillType]
        } else {
            $product = @{ En = $fillType.ToLowerInvariant(); De = $fillType }
        }

        $amountEn = Format-ProductionAmount -Amount $amountPerHour -CultureName "en-US"
        $amountDe = Format-ProductionAmount -Amount $amountPerHour -CultureName "de-DE"

        Set-L10nText -ModDesc $modDesc -Name $item.L10nName `
            -EnglishText "Produces $amountEn l $($product.En) per in-game hour." `
            -GermanText "Produziert $amountDe l $($product.De) pro Ingame-Stunde."
    }

    $settings = New-Object System.Xml.XmlWriterSettings
    $settings.Encoding = New-Object System.Text.UTF8Encoding($false)
    $settings.Indent = $false
    $settings.NewLineChars = "`r`n"

    $writer = [System.Xml.XmlWriter]::Create($modDescPath, $settings)
    try {
        $modDesc.Save($writer)
    }
    finally {
        $writer.Close()
    }
}

if ([string]::IsNullOrWhiteSpace($ModsPath)) {
    $candidates = @(
        (Join-Path $env:USERPROFILE "OneDrive\Dokumente\My Games\FarmingSimulator2025\mods"),
        (Join-Path $env:USERPROFILE "Documents\My Games\FarmingSimulator2025\mods")
    )

    foreach ($candidate in $candidates) {
        if (Test-Path -LiteralPath $candidate) {
            $ModsPath = $candidate
            break
        }
    }
}

if ([string]::IsNullOrWhiteSpace($ModsPath)) {
    throw "Kein FarmingSimulator2025 mods Ordner gefunden. Starte z.B.: .\build.ps1 -ModsPath 'C:\Users\pasca\OneDrive\Dokumente\My Games\FarmingSimulator2025\mods'"
}

if (-not (Test-Path -LiteralPath $ModsPath)) {
    New-Item -ItemType Directory -Force -Path $ModsPath | Out-Null
}

Update-ProductionDescriptions -ProjectRoot $projectRoot

Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem

if (Test-Path -LiteralPath $tempZip) {
    Remove-Item -LiteralPath $tempZip -Force
}

if (Test-Path -LiteralPath $projectZip) {
    Remove-Item -LiteralPath $projectZip -Force
}

$zip = [System.IO.Compression.ZipFile]::Open($tempZip, [System.IO.Compression.ZipArchiveMode]::Create)
try {
    $files = Get-ChildItem -LiteralPath $projectRoot -Recurse -File -Force | Where-Object {
        $relative = $_.FullName.Substring($projectRoot.Length + 1)
        -not ($relative -like ".git\*") -and
        -not ($relative -like ".vscode\*") -and
        $relative -ne "$modName.zip" -and
        $relative -ne "build.ps1" -and
        $relative -ne "build.cmd" -and
        -not ($relative -like "*.xcf")
    }

    foreach ($file in $files) {
        $relative = $file.FullName.Substring($projectRoot.Length + 1).Replace("\", "/")
        [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $file.FullName, $relative, [System.IO.Compression.CompressionLevel]::Optimal) | Out-Null
    }
}
finally {
    $zip.Dispose()
}

Move-Item -LiteralPath $tempZip -Destination $projectZip -Force
Copy-Item -LiteralPath $projectZip -Destination (Join-Path $ModsPath "$modName.zip") -Force

Write-Host "Build fertig: $projectZip"
Write-Host "Kopiert nach: $(Join-Path $ModsPath "$modName.zip")"
