[CmdletBinding(DefaultParameterSetName = 'Sid')]
param(
    [Parameter(Mandatory)]
    [string] $OracleHost,

    [Parameter(Mandatory)]
    [ValidateRange(1, 65535)]
    [int] $OraclePort,

    [Parameter(Mandatory, ParameterSetName = 'Sid')]
    [string] $OracleSid,

    [Parameter(Mandatory, ParameterSetName = 'ServiceName')]
    [string] $OracleServiceName,

    [Parameter(Mandatory)]
    [string] $OracleUserName,

    [Parameter(Mandatory)]
    [string] $MariaDbHost,

    [Parameter(Mandatory)]
    [ValidateRange(1, 65535)]
    [int] $MariaDbPort,

    [Parameter(Mandatory)]
    [string] $MariaDbDatabase,

    [Parameter(Mandatory)]
    [string] $MariaDbUserName,

    [ValidateSet('Disabled', 'Preferred', 'Required', 'VerifyCertificate', 'VerifyIdentity')]
    [string] $MariaDbTlsMode = 'Preferred',

    [string] $OutputPath = (Join-Path $env:LOCALAPPDATA 'MBN_STOCK_WEBVIEW\Config\database.local.json')
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function ConvertTo-PlainText {
    param([Parameter(Mandatory)][Security.SecureString] $SecureValue)

    $pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureValue)
    try {
        return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer)
    }
    finally {
        [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer)
    }
}

$oraclePassword = Read-Host 'Oracle password' -AsSecureString
$mariaDbPassword = Read-Host 'MariaDB password' -AsSecureString

try {
    $configuration = [ordered]@{
        oracle = [ordered]@{
            host = $OracleHost
            port = $OraclePort
            sid = if ($PSCmdlet.ParameterSetName -eq 'Sid') { $OracleSid } else { $null }
            serviceName = if ($PSCmdlet.ParameterSetName -eq 'ServiceName') { $OracleServiceName } else { $null }
            userName = $OracleUserName
            password = ConvertTo-PlainText $oraclePassword
            connectTimeoutSeconds = 10
            commandTimeoutSeconds = 30
            pooling = $true
        }
        mariaDb = [ordered]@{
            host = $MariaDbHost
            port = $MariaDbPort
            database = $MariaDbDatabase
            userName = $MariaDbUserName
            password = ConvertTo-PlainText $mariaDbPassword
            tlsMode = $MariaDbTlsMode
            connectTimeoutSeconds = 10
            commandTimeoutSeconds = 30
            pooling = $true
        }
        resilience = [ordered]@{
            operationTimeoutSeconds = 45
            maximumRetryCount = 2
            initialRetryDelayMilliseconds = 250
        }
    }

    $fullPath = [IO.Path]::GetFullPath($OutputPath)
    $directory = [IO.Path]::GetDirectoryName($fullPath)
    [IO.Directory]::CreateDirectory($directory) | Out-Null
    $json = $configuration | ConvertTo-Json -Depth 5
    [IO.File]::WriteAllText($fullPath, $json, [Text.UTF8Encoding]::new($false))

    $identity = [Security.Principal.WindowsIdentity]::GetCurrent().Name
    $acl = [Security.AccessControl.FileSecurity]::new()
    $acl.SetAccessRuleProtection($true, $false)
    $rule = [Security.AccessControl.FileSystemAccessRule]::new(
        $identity,
        [Security.AccessControl.FileSystemRights]::FullControl,
        [Security.AccessControl.AccessControlType]::Allow)
    $acl.AddAccessRule($rule)
    [IO.File]::SetAccessControl($fullPath, $acl)

    Write-Host "Database configuration created at: $fullPath"
    Write-Warning 'This user-only file contains plaintext passwords. Do not copy it into the repository or attach it to logs.'
}
finally {
    $oraclePassword.Dispose()
    $mariaDbPassword.Dispose()
    $configuration = $null
    $json = $null
}
