# Fix-Passwords.ps1
# Resets password hashes for both SuperAdmin users in the Azure SQL database.
# Runs directly via sqlcmd to avoid copy-paste corruption of Base64 characters.
#
# Usage (interactive - will prompt for connection details):
#   .\Fix-Passwords.ps1
#
# Usage (non-interactive):
#   .\Fix-Passwords.ps1 -Server "yourserver.database.windows.net" -Database "PowderCoatingDb" -User "sqladmin" -Password "yourpassword"

param(
    [string]$Server,
    [string]$Database = "PowderCoatingapp",
    [string]$User,
    [string]$Password
)

function New-IdentityPasswordHash {
    param([string]$Password)

    $salt = [byte[]]::new(16)
    $rng  = [System.Security.Cryptography.RandomNumberGenerator]::Create()
    $rng.GetBytes($salt)
    $rng.Dispose()

    $pbkdf2 = [System.Security.Cryptography.Rfc2898DeriveBytes]::new(
        $Password, $salt, 100000,
        [System.Security.Cryptography.HashAlgorithmName]::SHA256)
    $subkey = $pbkdf2.GetBytes(32)
    $pbkdf2.Dispose()

    # ASP.NET Core Identity v3 format
    $buf = [byte[]]::new(61)
    $buf[0]  = 0x01
    $buf[1]  = 0x00; $buf[2]  = 0x00; $buf[3]  = 0x00; $buf[4]  = 0x01   # PRF = HMACSHA256
    $buf[5]  = 0x00; $buf[6]  = 0x01; $buf[7]  = 0x86; $buf[8]  = 0xA0   # 100000 iterations
    $buf[9]  = 0x00; $buf[10] = 0x00; $buf[11] = 0x00; $buf[12] = 0x10   # salt length = 16
    [Array]::Copy($salt,   0, $buf, 13, 16)
    [Array]::Copy($subkey, 0, $buf, 29, 32)

    return [Convert]::ToBase64String($buf)
}

# ---- Prompt for connection details if not provided ----------------------------

if (-not $Server) {
    $Server = Read-Host "Azure SQL Server (e.g. yourserver.database.windows.net)"
}
if (-not $User) {
    $User = Read-Host "SQL Username"
}
if (-not $Password) {
    $securePass = Read-Host "SQL Password" -AsSecureString
    $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
        [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePass))
}

# ---- Check sqlcmd is available -----------------------------------------------

$sqlcmd = Get-Command sqlcmd -ErrorAction SilentlyContinue
if (-not $sqlcmd) {
    Write-Host ""
    Write-Host "ERROR: sqlcmd not found on PATH." -ForegroundColor Red
    Write-Host "Install it from: https://learn.microsoft.com/en-us/sql/tools/sqlcmd/sqlcmd-utility" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Alternatively, copy fix_passwords.sql to the Azure Portal Query Editor manually." -ForegroundColor Yellow
    Write-Host "(Be careful that + and / characters are not changed during copy-paste.)" -ForegroundColor Yellow
    $useSqlCmd = $false
} else {
    $useSqlCmd = $true
}

# ---- Generate hashes ---------------------------------------------------------

Write-Host ""
Write-Host "Generating password hashes..." -ForegroundColor Cyan
$hash1 = New-IdentityPasswordHash "SuperAdmin123!"
$hash2 = New-IdentityPasswordHash "CompanyAdmin123!"
$stamp1 = [Guid]::NewGuid().ToString()
$stamp2 = [Guid]::NewGuid().ToString()
Write-Host "Done." -ForegroundColor Cyan

# ---- Build SQL ---------------------------------------------------------------

$sql = @"
SET QUOTED_IDENTIFIER ON;
SET NOCOUNT ON;

-- Reset password hash for superadmin@powdercoating.com / SuperAdmin123!
UPDATE AspNetUsers
SET
    PasswordHash   = '$hash1',
    SecurityStamp  = '$stamp1'
WHERE NormalizedEmail = 'SUPERADMIN@POWDERCOATING.COM';

PRINT 'Updated: superadmin@powdercoating.com';

-- Reset password hash for admin@demo.com / CompanyAdmin123!
UPDATE AspNetUsers
SET
    PasswordHash   = '$hash2',
    SecurityStamp  = '$stamp2'
WHERE NormalizedEmail = 'ADMIN@DEMO.COM';

PRINT 'Updated: admin@demo.com';

-- Verify both users exist and have non-null hashes
SELECT Email, LEN(PasswordHash) AS HashLength, IsActive
FROM AspNetUsers
WHERE NormalizedEmail IN ('SUPERADMIN@POWDERCOATING.COM', 'ADMIN@DEMO.COM');
"@

# ---- Write SQL file (always, as backup) --------------------------------------

$sqlFile = Join-Path $PSScriptRoot "fix_passwords.sql"
$sql | Set-Content -Path $sqlFile -Encoding UTF8
Write-Host "SQL written to: $sqlFile" -ForegroundColor Gray

# ---- Execute via sqlcmd (avoids copy-paste corruption) -----------------------

if ($useSqlCmd) {
    Write-Host ""
    Write-Host "Running via sqlcmd (no copy-paste, Base64 characters preserved)..." -ForegroundColor Cyan

    $result = & sqlcmd `
        -S $Server `
        -d $Database `
        -U $User `
        -P $Password `
        -Q $sql `
        -l 30 2>&1

    Write-Host ""
    $result | ForEach-Object { Write-Host $_ }

    if ($LASTEXITCODE -eq 0) {
        Write-Host ""
        Write-Host "SUCCESS. Try logging in now:" -ForegroundColor Green
        Write-Host "  superadmin@powdercoating.com / SuperAdmin123!" -ForegroundColor White
        Write-Host "  admin@demo.com / CompanyAdmin123!" -ForegroundColor White
    } else {
        Write-Host ""
        Write-Host "sqlcmd returned exit code $LASTEXITCODE. Check the output above." -ForegroundColor Red
        Write-Host "You can also run fix_passwords.sql manually in the Azure Portal Query Editor." -ForegroundColor Yellow
    }
} else {
    Write-Host ""
    Write-Host "Run fix_passwords.sql in Azure Portal > SQL Database > Query Editor." -ForegroundColor Yellow
    Write-Host "TIP: If + or / appear as spaces after pasting, the hash will be corrupted again." -ForegroundColor Yellow
    Write-Host "     Use sqlcmd instead to be safe." -ForegroundColor Yellow
}
