#requires -Version 5.1
<#
.SYNOPSIS
    Install EMDS-Workbench Python dependencies into the QGIS-bundled Python on Windows.

.DESCRIPTION
    EMDS-Workbench needs pandas and pyarrow in the SAME Python that QGIS runs.
    A clean QGIS install (standalone qgis.org or OSGeo4W without the optional
    packages) does not ship these, so the plugin fails to load. This script
    locates the QGIS-bundled Python and installs only what is missing.

    Behaviour:
      * pandas is installed (pinned <3 for parity with the QGIS 4.0 macOS bundle)
        ONLY if it is not already importable. An existing pandas is left alone.
      * pyarrow is installed ONLY if it is not already importable.
      * If the bundle's site-packages is not writable (e.g. under Program Files),
        the script falls back to a per-user install automatically. Re-run from an
        elevated PowerShell for a system-wide install instead.

    Supports both OSGeo4W (C:\OSGeo4W) and standalone "QGIS X.Y.Z" installs.

.PARAMETER QgisPython
    Optional explicit path to the QGIS python.exe. Use this if auto-detection
    picks the wrong interpreter (e.g. multiple QGIS installs).

.PARAMETER UseUserSite
    Force a per-user (--user) install even if the bundle site is writable.

.EXAMPLE
    pwsh -File scripts\windows\install-deps.ps1

.EXAMPLE
    pwsh -File scripts\windows\install-deps.ps1 -QgisPython "C:\OSGeo4W\apps\Python312\python.exe"
#>
[CmdletBinding()]
param(
    [string]$QgisPython,
    [switch]$UseUserSite
)

$ErrorActionPreference = 'Stop'

# import-name => pip requirement spec (install-if-missing)
$Required = [ordered]@{
    'pandas'  = 'pandas>=2.0,<3'
    'pyarrow' = 'pyarrow>=14.0.0'
}

function Find-QgisPython {
    if ($QgisPython) {
        if (-not (Test-Path $QgisPython)) {
            throw "Specified -QgisPython does not exist: $QgisPython"
        }
        return (Resolve-Path $QgisPython).Path
    }

    $candidates = New-Object System.Collections.Generic.List[string]

    # OSGeo4W: target apps\Python3xx\python.exe directly. NEVER use
    # C:\OSGeo4W\bin\python.exe (a launcher shim that crashes when run outside
    # the o4w_env environment).
    foreach ($root in @('C:\OSGeo4W', 'C:\OSGeo4W64')) {
        $appsDir = Join-Path $root 'apps'
        if (Test-Path $appsDir) {
            Get-ChildItem $appsDir -Directory -Filter 'Python3*' -ErrorAction SilentlyContinue |
                ForEach-Object {
                    $candidates.Add((Join-Path $_.FullName 'python.exe'))
                }
        }
    }

    # Standalone "QGIS X.Y.Z" under Program Files.
    foreach ($pf in @($env:ProgramFiles, ${env:ProgramFiles(x86)})) {
        if (-not $pf) { continue }
        Get-ChildItem $pf -Directory -Filter 'QGIS*' -ErrorAction SilentlyContinue |
            ForEach-Object {
                $appsDir = Join-Path $_.FullName 'apps'
                if (Test-Path $appsDir) {
                    Get-ChildItem $appsDir -Directory -Filter 'Python3*' -ErrorAction SilentlyContinue |
                        ForEach-Object {
                            $candidates.Add((Join-Path $_.FullName 'python.exe'))
                        }
                }
            }
    }

    $found = $candidates | Where-Object { Test-Path $_ } | Select-Object -Unique
    if (-not $found) {
        throw "No QGIS-bundled Python found. Install QGIS, or pass -QgisPython <path-to-python.exe>."
    }
    if (@($found).Count -gt 1) {
        Write-Warning ("Multiple QGIS Python interpreters found; using the first. " +
            "Override with -QgisPython if this is wrong:`n  " + ($found -join "`n  "))
    }
    return @($found)[0]
}

function Test-DirWritable {
    param([string]$Dir)
    if (-not $Dir -or -not (Test-Path $Dir)) { return $false }
    try {
        $probe = Join-Path $Dir ('.emds_w_' + [guid]::NewGuid().ToString('N'))
        [IO.File]::WriteAllText($probe, 'x')
        Remove-Item $probe -Force
        return $true
    } catch {
        return $false
    }
}

function Test-Importable {
    param([string]$Python, [string]$Module)
    & $Python -c "import $Module" 2>$null
    return ($LASTEXITCODE -eq 0)
}

$py = Find-QgisPython
Write-Host "QGIS Python: $py"

# Add QGIS bin directory to PATH to prevent missing DLL issues (e.g. vcruntime140.dll)
$pyDir = Split-Path $py -Parent
$qgisBin = Resolve-Path (Join-Path $pyDir "..\..\bin") -ErrorAction SilentlyContinue
if ($qgisBin -and (Test-Path $qgisBin)) {
    $env:PATH = "$($qgisBin.Path);$env:PATH"
}

& $py --version

# Decide install target and check write permissions.
$siteDirRaw = & $py -c "import sysconfig; print(sysconfig.get_paths()['purelib'])" 2>$null
if ($LASTEXITCODE -ne 0 -or -not $siteDirRaw) {
    throw "Failed to execute QGIS Python. Please verify that Visual C++ Redistributable is installed and QGIS is fully functional."
}
$siteDir = $siteDirRaw.Trim()
$isWritable = Test-DirWritable $siteDir
$useUser = $UseUserSite -or -not $isWritable

# Ensure pip is present.
& $py -m pip --version 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
    Write-Host "pip not found; bootstrapping with ensurepip..."
    $ensurepipArgs = @('-m', 'ensurepip', '--upgrade')
    if ($useUser) {
        $ensurepipArgs += '--user'
        if (-not $UseUserSite) {
            Write-Warning ("site-packages is not writable ($siteDir). Bootstrapping pip to " +
                "user directory. Re-run from an elevated PowerShell for a system-wide install.")
        }
    }
    & $py @ensurepipArgs
    if ($LASTEXITCODE -ne 0) { throw "Could not bootstrap pip into the QGIS Python." }
}

$pipArgs = @('-m', 'pip', 'install', '--no-input', '--disable-pip-version-check')
if ($useUser) {
    $pipArgs += '--user'
}

foreach ($module in $Required.Keys) {
    $spec = $Required[$module]
    if (Test-Importable -Python $py -Module $module) {
        $ver = (& $py -c "import $module as m; print(getattr(m,'__version__','?'))").Trim()
        Write-Host "  OK: '$module' already present ($ver) - leaving it unchanged."
        continue
    }
    Write-Host "  Installing $spec ..."
    & $py @pipArgs $spec
    if ($LASTEXITCODE -ne 0) { throw "pip install failed for $spec" }
}

# Verify.
Write-Host "Verifying imports in the QGIS Python..."
& $py -c "import pandas, pyarrow; print('OK  pandas', pandas.__version__, '| pyarrow', pyarrow.__version__)"
if ($LASTEXITCODE -ne 0) { throw "Post-install import verification failed." }

Write-Host "Dependencies satisfied. Restart QGIS so the plugin picks them up." -ForegroundColor Green