#################
# CEDAR version upgrade script. Upgrades e.g. CEDAR 2024.0101 to 2024.0601.
#################

##########################
# September 2024: Removed dependence on install.ps1 (nightmare spaghetti code).
#
# This script is ONLY dependent on vars.ps1 and NOTHING ELSE.
##########################

param (
    # DBATools can be _very_ slow to install & can be skipped if already installed:
    [Switch] $SkipDBAToolsInstall

    # Globals Block. Here for autocomplete:
    # See file `vars.ps1` for values of each.
    , [string]$Global:version
    , [string]$Global:PHP_VERSION
    , [string]$Global:PHP_VERSION_FULL
    , [string]$Global:POWERSHELL_VERSION
    , [string]$Global:SchemaZenVersion
    , [string]$Global:ROOT
    , [string]$Global:PHPdir
    , [string]$Global:PHPexe
    , [string]$Global:CEDAR
    , [string]$Global:InstalledPHPexe
    , [string]$Global:IISexe
    , [string]$Global:GITexe
    , [string]$Global:SchemaZen
    , [string]$Global:ZIPexe
    , [string]$Global:CedarReleases
    , [bool]$Global:IsAdministrator
)

# Import globals:
&"$PSScriptRoot\vars.ps1"

# Legacy variables to support RS old spaghetti powershell:
$Global:CEDAR_VERSION = $version
$Global:CEDAR_DATABASES = "CEDAR_LIVE", "CISA_LIVE"
$Global:CEDAR_DATABASES_ACTION_TEST = $false
$Global:CEDAR_SQL_INSTALL_DIR = "C:\SQL2022Media"
$Global:CEDAR_SQL_SERVER_VERSION = "2022"
$Global:CEDAR_SQL_SERVER_ID = "16"
$Global:CEDAR_RELEASE_DOMAIN = $CedarReleases


function main()
{
    # System Parameters
    # $ProgressPreference = 'SilentlyContinue'
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

    if (!$IsAdministrator) {
        throw "Must be an admin to upgrade CEDAR. Re-launch your terminal as Administrator."
    }


    CEDAR_PATH_EXTRACT
    CEDAR_FILES

    # $confPerms = (Read-Host "Do you want reset permissions (later in the process)? (y): ").ToLower()
    $confPerms = "n"

    $INSTALLED_VERSION = Get-Content "$ROOT/version.txt"
    if ($null -ne $INSTALLED_VERSION -And $null -ne $CEDAR_VERSION -AND $INSTALLED_VERSION -ne $CEDAR_VERSION)
    {
        Write-Host "Installed Version: $INSTALLED_VERSION"
        Write-Host "Latest Version: $CEDAR_VERSION"
        $confExtract = (Read-Host "Do you want to extract CEDAR files over this folder? (y): ").ToLower()
        if ($confExtract -eq 'y')
        {
            Write-Host "Extracting....."
            try
            {
                CEDAR_INSTALL_FILES_ENCRYPTED
            }
            catch
            {
                throw "Extraction failed"
            }
        }
    }

    try {
        Import-Module PhpManager -ErrorAction Stop
    } catch {
        Install-Module PhpManager -Repository PSGallery -Confirm:$false -Force
        Import-Module PhpManager
    }


    if ($SkipDBAToolsInstall)
    {
        Write-Host "DBATools install skipped."
    }
    else
    {
        FN_DBATOOLS
    }


    # $confMaintain = (Read-Host "Enable Maintenance mode? (y): ").ToLower()
    $confMaintain = 'n'
    if ($confMaintain -eq 'y')
    {
        &"$PHPexe" "$ROOT/src/bootstrap.php" config:edit ENABLE_MAINTENANCE_MODE 1 1
    }

    $phpOutput = &"$InstalledPHPexe" -v

    if (-Not ($phpOutput -match "$PHP_VERSION_FULL"))
    {
        Write-Host "PHP Version upgrade"
        upgradePHP
    }

    #$confBackup = (Read-Host "Do you want to backup the databases? (y): ").ToLower()
    $confBackup = 'n'
    if ($confBackup -eq 'y')
    {
        &"$PHPexe" "$ROOT/src/bootstrap.php" upgrade:backup:sql
    }

    downloadPhpVendorPackages

    if (-Not (Test-Path "$ROOT/vendor/autoload.php" -PathType Leaf))
    {
        Write-Host "ERROR | Could not complete pulling dependencies. Please screenshot and send to CEDAR. (Error could be due to your firewall)"
        exit
    }

    # Todo: Fix or supress deprecation warnings interferring with this check:
#    $res = (&"$PHPexe" "$ROOT\Scripts\upgradeCommand.php" "upgrade:check") | Out-String
#    if (-Not ($res.Trim() -eq "OK"))
#    {
#
#        throw "Failed to parse .env file. Check for single backslash and missing quote marks. Some additional details: $res"
#    }

    setLatestReleaseVersion

    Expand-Archive -Force "$ROOT/Var/Upgrade/$version.sql.zip" -DestinationPath "$ROOT/"

    Write-Host ""

    try
    {
        ENV_READ
        if ($null -eq $CISA_DATABASE)
        {
            throw "Unknown CISA_DATABASE in .\Config\.env"
        }

        Write-Host "Setting DB Credentials"
        CEDAR_FN_DATABASE_LOCATION_CHECK

        Write-Host "Migration scripts begin"
        DB_QUERY_FILE $DB_SERVER $Global:CISA_DATABASE "$ROOT/$version.cisa.sql"
        Write-Host "CISA Migration script complete"
        DB_QUERY_FILE $DB_SERVER $Global:DB_DATABASE "$ROOT/$version.cedar.sql"
        Write-Host "CEDAR Migration script complete"
    }
    catch
    {
        $confDBRun = (Read-Host "Have you run the '$version.cedar.sql' and '$version.cisa.sql' upgrade scripts (in this directory) against the relevant databases ? (y): ").ToLower()
        if (-Not ($confDBRun -eq 'y'))
        {
            exit
        }
    }


    Write-Host "upgrade:scripts"
    runUpgradeScripts

    # Run the Database Sync - So no need to login
    Write-Host 'upgrade:db:sync'
    &"$PHPexe" "$ROOT/src/bootstrap.php" "upgrade:db:sync"

    Write-Host 'cache:db'
    &"$PHPexe" "$ROOT/src/bootstrap.php" "cache:db"

    ## Final Checks

    Write-Host 'upgrade:patch'
    &"$PHPexe" "$ROOT/src/bootstrap.php" "upgrade:patch"

    $confSuccess = (Read-Host "Did everything complete successfully? (y): ").ToLower()
    if ($confSuccess -eq 'y')
    {
        Write-Host 'clean up'

        cleanupUpgradeFiles

        Write-Host 'upgrade:notify'
        &"$PHPexe" "$ROOT/src/bootstrap.php" "upgrade:notify"

        if ($confMaintain -eq 'y')
        {
            &"$PHPexe" "$ROOT/src/bootstrap.php" config:edit ENABLE_MAINTENANCE_MODE 0 1
        }
    }

    Write-Host "Upgrade Complete"

    if ($true -eq $IIS_RUNNING)
    {
        $confIisStart = (Read-Host "Do you want to start IIS? (n): ").ToLower()
        if ($confIisStart -eq 'y')
        {
            iisreset.exe /start
            $Global:IIS_RUNNING = $true
        }
    }
}

function downloadPhpVendorPackages
{
    $SAVE_DRIVE = "C:"

    if (-Not(Test-Path -Path "$SAVE_DRIVE\$CEDAR_VERSION.vendor.zip"))
    {
        Write-Host "Fetch $CEDAR_RELEASE_DOMAIN/$CEDAR_VERSION.vendor.zip"
        try
        {
            [void](Invoke-WebRequest -Uri "$CEDAR_RELEASE_DOMAIN/$CEDAR_VERSION.vendor.zip" -OutFile "$SAVE_DRIVE\$CEDAR_VERSION.vendor.zip" -SkipCertificateCheck)
        }
        catch
        {
            throw "Failed to download"
        }
    }

#    ForEach ($dir in $CEDAR_INSTALL_DIRS)
#    {
#        Write-Host "Deleting vendor folder in $CEDAR_INSTALL_BASE/$dir"
#        Remove-Item "$CEDAR_INSTALL_BASE/$dir/vendor/" -Recurse -Force
#
#        Write-Host "Extracting vendor folder in $CEDAR_INSTALL_BASE/$dir"
#        Expand-Archive  -Force "$SAVE_DRIVE/$CEDAR_VERSION.vendor.zip" -DestinationPath "$CEDAR_INSTALL_BASE/$dir/"
#
#        Write-Host "Compser dumpautoload"
#        php "$CEDAR_INSTALL_BASE/$dir/Var/composer.phar" --working-dir="$CEDAR_INSTALL_BASE/$dir/Var/" --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --optimize-autoloader --prefer-dist install
#    }
}

function CEDAR_PATH_EXTRACT
{
    $CWD = (Get-Location)
    if (-Not(Test-Path -Path "$CWD/")) {
        throw "Not a CEDAR folder"
    }

    $Global:CEDAR_INSTALL_DIRS = Split-Path -Path (Get-Location) -Leaf
    $Global:CEDAR_INSTALL_BASE = (Get-Location) | Split-Path

    Write-Host "CEDAR_INSTALL_DIRS: $CEDAR_INSTALL_DIRS"
    Write-Host "CEDAR_INSTALL_BASE: $CEDAR_INSTALL_BASE"

    [Environment]::SetEnvironmentVariable('CEDAR_INSTALL_BASE', $CEDAR_INSTALL_BASE, 'Machine')
    [Environment]::SetEnvironmentVariable('CEDAR_INSTALL_DIRS', $CEDAR_INSTALL_DIRS -join ",", 'Machine')
}

function CEDAR_FILES
{
    $SAVE_DRIVE = "C:"

    if ($null -ne $args[0]) {
        Write-Host "Using version :" + $args[0]
        $CEDAR_VERSION = $args[0]
    } else {
        CEDAR_VERSION_FETCH
    }

    $CEDAR_ZIP_FILE = "$CEDAR_VERSION.files.zip"
    $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/$CEDAR_ZIP_FILE"
    Write-Host "$FETCH_FILE"
    if (-Not(Test-Path -Path $FETCH_FILE -Type Leaf))
    {
        Invoke-WebRequest $FETCH_FILE -OutFile "$SAVE_DRIVE\$CEDAR_ZIP_FILE"
    }

    $CEDAR_ZIP_FILE = "$CEDAR_VERSION.sql.zip"
    $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/$CEDAR_ZIP_FILE"
    Write-Host "$FETCH_FILE"
    if (-Not(Test-Path -Path $FETCH_FILE -Type Leaf))
    {
        Invoke-WebRequest $FETCH_FILE -OutFile "$SAVE_DRIVE\$CEDAR_ZIP_FILE"
    }

    $CEDAR_ZIP_FILE = "$CEDAR_VERSION.vendor.zip"
    $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/$CEDAR_ZIP_FILE"
    Write-Host "$FETCH_FILE"
    if (-Not(Test-Path -Path $FETCH_FILE -Type Leaf))
    {
        Invoke-WebRequest $FETCH_FILE -OutFile "$SAVE_DRIVE\$CEDAR_ZIP_FILE"
    }

    $CEDAR_ZIP_FILE = "$CEDAR_VERSION.scripts.zip"
    $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/$CEDAR_ZIP_FILE"
    Write-Host "$FETCH_FILE"
    if (-Not(Test-Path -Path $FETCH_FILE -Type Leaf))
    {
        Invoke-WebRequest $FETCH_FILE -OutFile "$SAVE_DRIVE\$CEDAR_ZIP_FILE"
    }

    if ($null -eq $CEDAR_INSTALL_DIRS)
    {
        return
    }

    ForEach ($dir in $CEDAR_INSTALL_DIRS)
    {
        $CEDAR_INSTALL_BASE | oss
        Write-Host "Copying files to $CEDAR_INSTALL_BASE/$dir\Var\Upgrade\"
        Copy-Item -Path "$SAVE_DRIVE/$CEDAR_VERSION.*.zip" -Destination "$CEDAR_INSTALL_BASE/$dir\Var\Upgrade\"
    }
}



function CEDAR_INSTALL_FILES_ENCRYPTED
{
    CEDAR_PS_VARS_SETUP

    $CEDAR_INSTALL_ZIP_FILE = "C:/$CEDAR_VERSION.files.zip"

    if (-Not(Test-Path -Type Leaf -Path "$CEDAR_INSTALL_ZIP_FILE"))
    {
        $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/$CEDAR_VERSION.files.zip"
        Write-Host "Downloading: $FETCH_FILE"
        Invoke-WebRequest $FETCH_FILE -OutFile $CEDAR_INSTALL_ZIP_FILE
        if (-NOT(Test-Path -Type Leaf -Path $CEDAR_INSTALL_ZIP_FILE))
        {
            Throw "Not Found: $CEDAR_INSTALL_ZIP_FILE"
        }
    }

    ForEach ($dir in $CEDAR_INSTALL_DIRS)
    {
        Expand-Archive -Force "$CEDAR_INSTALL_ZIP_FILE" -DestinationPath "$CEDAR_INSTALL_BASE/$dir"
    }

    CEDAR_INSTALL_DIR_PERMISSIONS
}

function CEDAR_PS_VARS_SETUP
{
    CWD
}

function CWD
{
    $global:CWD = [string](Get-Location)

    return $CWD
}


function CEDAR_INSTALL_DIR_PERMISSIONS
{
    CEDAR_USER_CHECK_SET

    Write-Host "Adding Permissions for $CEDAR_INSTALL_USERS"

    $user = $CEDAR_INSTALL_USERS | Select-Object -First 1
    Write-Host "Setting to : $user"

    CEDAR_PATH_CHECK_OR_EXTRACT

    ForEach ($dir in $CEDAR_INSTALL_DIRS)
    {
        $installPath = "$CEDAR_INSTALL_BASE/$dir"
        Write-Host "Creating $installPath"
        [void](New-Item -Path $installPath -Type Directory -Force -ErrorAction Continue)
        $acl = Get-Acl $installPath
        ForEach ($usr in $CEDAR_INSTALL_USERS)
        {
            $a = New-Object System.Security.AccessControl.FileSystemAccessRule($usr, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
            $acl.AddAccessRule($a)
        }

        $acl.SetAccessRuleProtection($False, $True)
        $acl.SetOwner([System.Security.Principal.NTAccount]$user)
        Set-Acl $installPath $acl
    }
}

function CEDAR_USER_CHECK_SET
{
    try
    {
        Get-Variable "CEDAR_INSTALL_USERS" -ErrorAction Stop
    }
    Catch
    {
        CEDAR_USER_SET
    }
}

function CEDAR_USER_SET
{
    $Global:CEDAR_INSTALL_USERS = "IUSR", "IIS_IUSRS", $env:UserName
    [Environment]::SetEnvironmentVariable('CEDAR_INSTALL_USERS', $CEDAR_INSTALL_USERS -join ",", 'Machine')
}

function CEDAR_PATH_CHECK_OR_EXTRACT
{
    if ($null -eq $CEDAR_INSTALL_DIRS) {
        CEDAR_VARS_RESTORE
    }

    if ($null -eq $CEDAR_INSTALL_DIRS) {
        CEDAR_PATH_EXTRACT
    }
}


function CEDAR_VARS_RESTORE
{
    $Global:CEDAR_INSTALL_DIRS = ([Environment]::GetEnvironmentVariable('CEDAR_INSTALL_DIRS','Machine') -split ",")
    $Global:CEDAR_INSTALL_BASE = [Environment]::GetEnvironmentVariable('CEDAR_INSTALL_BASE','Machine')
    $Global:CEDAR_INSTALL_USERS = ([Environment]::GetEnvironmentVariable('CEDAR_INSTALL_USERS','Machine') -split ",")
    Write-Host "Variables restored"
    Write-Host "CEDAR_INSTALL_BASE"
    Write-Host $CEDAR_INSTALL_BASE
    Write-Host "CEDAR_INSTALL_DIRS"
    Write-Host $CEDAR_INSTALL_DIRS
    Write-Host "CEDAR_INSTALL_USERS"
    Write-Host $CEDAR_INSTALL_USERS
}

function ENV_READ
{
    CEDAR_PS_VARS_SETUP

    if (-Not(Test-Path -Path "$CWD/Config/.env" -Type Leaf))
    {
        return
    }

    try
    {
        $ConfigEnv = (Get-Content "$CWD/Config/.env" | Where-Object { $_ -match "=" }) | ForEach-Object { $_ -replace '"', '' } | ConvertFrom-StringData
        foreach ($h in $ConfigEnv.Keys)
        {
            Set-Variable -Name $h -Value $ConfigEnv.$h -Scope Global
        }
    }
    catch
    {
    }
}

function CEDAR_FN_DATABASE_LOCATION_CHECK
{
    ENV_READ

    $Global:MIS_DB_HOST = $null
    $Global:MIS_DB_INSTANCE = $null
    $Global:CEDAR_DB_HOST = $null
    $Global:CEDAR_DB_INSTANCE = $null

    if ($null -ne $MIS_SERVER)
    {
        $MIS_SERVER = $MIS_SERVER -replace ('\\', '\')


        if (($MIS_SERVER -match '\\') -eq $true)
        {
            $Global:MIS_DB_HOST = ($MIS_SERVER.split('\')[0])
            $Global:MIS_DB_INSTANCE = ($MIS_SERVER.split('\')[-1])
        }
        else
        {
            $Global:MIS_DB_HOST = $MIS_SERVER
            $Global:MIS_DB_INSTANCE = ''
        }
    }

    if ($null -ne $DB_SERVER)
    {
        if (($DB_SERVER -match '\\') -eq $true)
        {

            $Global:CEDAR_DB_HOST = ($DB_SERVER.split('\')[0])
            $Global:CEDAR_DB_INSTANCE = ($DB_SERVER.split('\')[-1])
        }
        else
        {
            $Global:CEDAR_DB_HOST = $DB_SERVER
            $Global:CEDAR_DB_INSTANCE = ''
        }
    }

    if ($null -ne $Global:DB_DATABASE -AND ($null -ne $Global:CISA_DATABASE))
    {
        [System.Collections.ArrayList]$Global:CEDAR_DATABASES = @()
        $Global:CEDAR_DATABASES += $Global:DB_DATABASE
        $Global:CEDAR_DATABASES += $Global:CISA_DATABASE
    } elseif (($null -ne $Global:DB_DATABASE) -AND ($Global:DB_DATABASE -match '_\w+$'))
    {
        $suffix = ($Global:DB_DATABASE -replace '\w+_(\w+)', '$1')

        [System.Collections.ArrayList]$Global:CEDAR_DATABASES = @()
        $Global:CEDAR_DATABASES += "CEDAR_$suffix"
        $Global:CEDAR_DATABASES += "CISA_$suffix"
    }

    $DB_PASS_CRED = ConvertTo-SecureString -String $Global:DB_PWD -AsPlainText -Force
    $Global:DB_CREDENTIALS = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Global:DB_UID, $DB_PASS_CRED

    if ($null -eq $CEDAR_DB_HOST -OR $null -eq $CEDAR_DB_INSTANCE)
    {
        CEDAR_FN_DATABASE_LOCATION
    }
    else
    {
        CEDAR_FN_DATABASES_PRINT
    }
}

function CEDAR_FN_DATABASES_PRINT
{
    Write-Host ""
    Write-Host "DB_SERVER: $DB_SERVER"
    Write-Host "CEDAR_DB_HOST: $CEDAR_DB_HOST"
    Write-Host "CEDAR_DB_INSTANCE: $CEDAR_DB_INSTANCE"
    Write-Host "CEDAR_DB: $DB_DATABASE"
    Write-Host "CISA_DB: $CISA_DATABASE"

    Write-Host ""
    Write-Host "MIS_SERVER: $MIS_SERVER"
    Write-Host "MIS_DB_HOST: $MIS_DB_HOST"
    Write-Host "MIS_DB_INSTANCE: $MIS_DB_INSTANCE"
    Write-Host "MIS_DATABASE: $MIS_DATABASE"

    Write-Host ""
    Write-Host "CEDAR Databases:"
    Write-Host $CEDAR_DATABASES
    Write-Host ""
}

function CEDAR_FN_DATABASE_LOCATION
{
    Write-Host ''
    Write-Host 'Define the location of the CEDAR + MIS Databases'
    Write-Host ''

    $Global:CEDAR_DB_HOST = 'localhost'
    $GLobal:CEDAR_DB_INSTANCE = 'MSSQLSERVER'

    $CEDAR_DB_INSTANCE = Read-Host "SQL Server Instance name for CEDAR? (localhost\MSSQLSERVER) "
    if (($CEDAR_DB_INSTANCE -match '\\') -eq $true)
    {
        $CEDAR_DB_HOST = ($CEDAR_DB_INSTANCE.split('\\')[0])
        $CEDAR_DB_INSTANCE = ($CEDAR_DB_INSTANCE.split('\\')[-1])
    }

    $Global:MIS_DB_HOST = 'localhost'
    $GLobal:MIS_DB_INSTANCE = ''

    $MIS_DB_INSTANCE = Read-Host "SQL Server Instance name for MIS? (localhost\MSSQLSERVER) "
    if (($MIS_DB_INSTANCE -match '\\') -eq $true)
    {
        $MIS_DB_HOST = ($MIS_DB_INSTANCE.split('\\')[0])
        $MIS_DB_INSTANCE = ($MIS_DB_INSTANCE.split('\\')[-1])
    }

    $CEDAR_DB_SUFFIX = Read-Host "CEDAR Database suffix? (e.g. TEST) "
    $CEDAR_DB_SUFFIX = $CEDAR_DB_SUFFIX.ToUpper()

    If (('' -eq $CEDAR_DB_SUFFIX) -OR ('LIVE' -eq $CEDAR_DB_SUFFIX))
    {
        $T_INSTALL_TEST = Read-Host "Do you also want to install ? CEDAR_TEST (Y/N) "
        if ('Y' -eq $T_INSTALL_TEST.ToUpper())
        {
            $CEDAR_DATABASES += 'CEDAR_TEST'
            $CEDAR_DATABASES += 'CISA_TEST'
            $CEDAR_DATABASES_ACTION_TEST = $true
        }
    }

    CEDAR_FN_DATABASES_PRINT
}

function DB_QUERY_FILE([string]$P_DB_SERVER, [string]$P_DB_DATABASE, [string]$P_FILE)
{
    if ($null -ne $DB_ALTER_USE_WINDOWS_USER -AND $DB_ALTER_USE_WINDOWS_USER -eq 1) {
        Invoke-DbaQuery -SqlInstance $P_DB_SERVER -Database $P_DB_DATABASE -File $P_FILE
        return
    }

    Invoke-DbaQuery -SqlInstance $P_DB_SERVER -Database $P_DB_DATABASE -File $P_FILE -SqlCredential $DB_CREDENTIALS
}

function setLatestReleaseVersion()
{
    #
    # Use a file "version.txt" in root of project to determine the name of the next release
    #

    $fileVer = "$PSScriptRoot/../version.txt"

    if (-Not (Test-Path $fileVer -PathType Leaf))
    {
        Write-Output 'version.txt not present in project root'
        exit
    }

    $versionLocal = (Get-Content -Path $fileVer).trim()

    $Global:version = $versionLocal -replace '\.\d{1,2}$', ''

    Write-Host "Version Detected`t| $version"

    if (-not ($version -eq $versionLocal))
    {
        Write-Host "Patch Detected  `t| $versionLocal"
    }
}

function runUpgradeScripts()
{
    if (-Not (Test-Path "$ROOT/Var/Upgrade/$version.scripts.zip" -PathType Leaf))
    {
        Write-Host "Downloading $version.scripts.zip"
        [void](Invoke-WebRequest -Uri "$CedarReleases/$version.scripts.zip" -OutFile "$ROOT/Var/Upgrade/$version.scripts.zip" -ErrorAction SilentlyContinue -SkipCertificateCheck)
    }

    Write-Host "Extracting $version.scripts.zip"
    Expand-Archive -Force "$ROOT/Var/Upgrade/$version.scripts.zip" -DestinationPath "$ROOT/Var/Upgrade/" -ErrorAction SilentlyContinue

    Write-Host ""
    Write-Host "upgrade SQL scripts"
    &"$PHPexe" "$ROOT/src/bootstrap.php" upgrade:scripts $version --live --single
    Write-Host ""
    Write-Host 'upgrade PS1 scripts'
    Get-ChildItem "$ROOT\Var\Upgrade\*.ps1" | ForEach-Object {
        $fName = $_.FullName
        Write-Host "Running ... $fName"
        &"$fName"
        [void](Remove-Item -Force "$fName")
    }
}


function upgradePHP()
{
    trap
    {
        iisreset /start
        throw $_
    }

    $phpVersion = $PHP_VERSION_FULL
    if ($args.count -eq 1)
    {
        $phpVersion = $args[0]
    }

    if (-Not ($phpVersion -match "^" + $PHP_VERSION))
    {
        Write-Host "PHP Version not in correct Major Version: $PHP_VERSION"
        exit
    }

    $zipFile = "$ROOT/Var/Upgrade/php.zip"
    $zipFolder = "$ROOT/Var/Upgrade/php"

    if (Test-Path $zipFile -PathType Leaf)
    {
        try
        {
            [void](Expand-Archive -Force $zipFile -DestinationPath $zipFolder)
        }
        catch
        {
            Remove-Item $zipFile -Force
        }
    }

    if (-Not (Test-Path $zipFile -PathType Leaf))
    {
        Write-Host "Begin download for PHP $phpVersion"
        $primaryUrl = "https://windows.php.net/downloads/releases/php-$phpVersion-nts-Win32-vs16-x64.zip"
        $backupUrl = "https://windows.php.net/downloads/releases/archives/php-$phpVersion-nts-Win32-vs16-x64.zip"

        try
        {
            Invoke-WebRequest -Uri $primaryUrl -OutFile $zipFile -SkipCertificateCheck
        }
        catch
        {
            if ($_.Exception.Response.StatusCode -eq 404)
            {
                Invoke-WebRequest -Uri $backupUrl -OutFile $zipFile -SkipCertificateCheck
            }
            else
            {
                throw $_
            }
        }
    }

    Expand-Archive -Force $zipFile -DestinationPath $zipFolder

    if ($StopIIS)
    {
        iisreset.exe /stop
        Stop-Process -Name php-cgi, php -Force -ErrorAction SilentlyContinue
    }

    [void](New-Item -Path $PHPdir -ItemType Directory -ErrorAction Continue -Force)
    Copy-Item -Force -Recurse "$zipFolder/*" "$PHPdir"

    $Global:PhpVOutput = &"$PHPexe" -v

    if ($PhpVOutput -match ".*" + "$phpVersion" + ".*")
    {
        Remove-Item $zipFile -Force
        Remove-Item "$zipFolder" -Recurse -Force

        $oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path
        # TODO if change in version
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v5\.6\\?", ""
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v7\.1\\?", ""
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v7\.2\\?", ""
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v7\.4\\?", ""
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v8\.0\\?", ""
        $oldpath = $oldpath -replace "C:\\Program Files\\PHP\\v8\.3\\?", ""
        $phpPath = "C:\Program Files\PHP\v$PHP_VERSION\";
        $newpath = "$oldpath;$phpPath"
        Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newpath

        Write-Host "Upgrade complete."
    }
    else
    {
        Write-Host "PHP Upgrade failed"
        Write-Host $PHPdir
        Write-Host $phpVersion
        Write-Host $PhpVOutput
    }

    iisreset /start
}

function cleanupUpgradeFiles()
{
    Remove-Item "$ROOT/*.msi"
    Remove-Item "$ROOT/*.sql"
    Remove-Item "$ROOT/*.zip"
    Remove-Item "$ROOT/Var/Upgrade/*.zip"
    Remove-Item "$ROOT/Var/Upgrade/*.json"
    [void](Remove-Item "$ROOT/Var/Upgrade/sg/" -Recurse -Force -ErrorAction SilentlyContinue)
    [void](Remove-Item "$ROOT/pre-upgrade.ps1" -Force)
}

function CEDAR_VERSION_FETCH
{
    $FETCH_FILE = "$CEDAR_RELEASE_DOMAIN/current.json"
    Write-Host "Downloading: $FETCH_FILE"

    try
    {
        $res = (Invoke-WebRequest $FETCH_FILE)
    }
    catch
    {
        if (-NOT(Test-Path -Type Leaf -Path $FETCH_FILE))
        {
            $msg = $_.Exception.Message
            throw "Could not download $FETCH_FILE. Error $msg"
        }

        $res = Get-Content $FETCH_FILE
    }

    try
    {
        $con = $res.Content
        $json = $con | ConvertFrom-JSON

        $Global:CEDAR_VERSION = $json.this

        Write-Host "Current Version: $CURRENT_VERSION"
    }
    catch
    {
        throw "Error getting latest version. Access $FETCH_FILE"
    }
}

function FN_DBATOOLS
{
    Write-Host "Installing DBATools. This may take a minute..."

    Install-Module -Name dbatools -RequiredVersion 2.0.0-preview2 -AllowPrerelease -SkipPublisherCheck -Confirm:$false -Repository PSGallery

    Write-Host "Setting SQL Encryption library to allow non-SSL"

    Set-DbatoolsConfig -Name Import.EncryptionMessageCheck -Value $false -PassThru | Register-DbatoolsConfig
    Set-DbatoolsConfig -FullName sql.connection.trustcert -Value $true -Register
    Set-DbatoolsConfig -FullName sql.connection.encrypt -Value $false -Register
}

main
