namespace SilverOS.Welcome.Core.Apply;
public sealed class BitLockerService(IProcessRunner runner) : IBitLockerService
{
    public async Task EnableAsync(string pin, CancellationToken ct = default)
    {
        var p = pin.Replace("'", "''");

        // 1. Set the FVE "Require additional authentication at startup" policy so the
        //    TPM+PIN protector is permitted. Without this, Enable-BitLocker -TpmAndPinProtector
        //    silently degrades to TPM-only (boots with no PIN prompt).
        // 2. Add the TPM+PIN protector — Enable-BitLocker if the volume is still decrypted,
        //    or Add-BitLockerKeyProtector if Windows automatic device-encryption already
        //    encrypted it with a TPM-only protector.
        // 3. Remove any TPM-only protector (only once a TPM+PIN protector is confirmed present)
        //    so the device actually requires the PIN at pre-boot.
        var script = string.Concat(
            // Eject optical install media first — BitLocker -TpmAndPinProtector refuses to enroll
            // while bootable CD/DVD media is present ("detected bootable media in the computer").
            "try { $s=New-Object -ComObject Shell.Application; ",
            "$s.Namespace(17).Items() | Where-Object { $_.Type -match 'CD|DVD' } | ForEach-Object { try { $_.InvokeVerb('Eject') } catch {} } } catch {}; ",
            "Start-Sleep -Seconds 3; ",
            "$fve='HKLM:\\SOFTWARE\\Policies\\Microsoft\\FVE'; ",
            "New-Item -Path $fve -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name UseAdvancedStartup -Value 1 -PropertyType DWord -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name EnableBDEWithNoTPM -Value 0 -PropertyType DWord -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name UseTPM -Value 2 -PropertyType DWord -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name UseTPMPIN -Value 2 -PropertyType DWord -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name UseTPMKey -Value 2 -PropertyType DWord -Force | Out-Null; ",
            "New-ItemProperty -Path $fve -Name UseTPMKeyPIN -Value 2 -PropertyType DWord -Force | Out-Null; ",
            "$mp=$env:SystemDrive; ",
            "$p=ConvertTo-SecureString '", p, "' -AsPlainText -Force; ",
            "$v=Get-BitLockerVolume -MountPoint $mp; ",
            "if ($v.VolumeStatus -eq 'FullyDecrypted') { ",
            // NO -SkipHardwareTest: let BitLocker run its hardware test on the next reboot so it
            // VALIDATES the TPM+PIN unseal against the real boot measurements before encrypting.
            // -SkipHardwareTest seals immediately against possibly-wrong PCRs -> drops to recovery
            // on first boot (E_FVE_SECURE_BOOT_CHANGED, PCR 11). The wizard's end-of-flow reboot
            // is that validation pass, so the PIN works on first boot instead of bouncing.
            "Enable-BitLocker -MountPoint $mp -EncryptionMethod XtsAes256 -TpmAndPinProtector -Pin $p } ",
            "elseif (-not ($v.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'TpmPin' })) { ",
            "Add-BitLockerKeyProtector -MountPoint $mp -TpmAndPinProtector -Pin $p }; ",
            "$kp=(Get-BitLockerVolume -MountPoint $mp).KeyProtector; ",
            "if ($kp | Where-Object { $_.KeyProtectorType -eq 'TpmPin' }) { ",
            "$kp | Where-Object { $_.KeyProtectorType -eq 'Tpm' } | ForEach-Object { ",
            "Remove-BitLockerKeyProtector -MountPoint $mp -KeyProtectorId $_.KeyProtectorId | Out-Null } }; ",
            // 4. Add a RECOVERY-PASSWORD protector so a forgotten/mistyped PIN is recoverable —
            //    TPM+PIN alone is an unrecoverable brick. Save the 48-digit key to ProgramData
            //    AND to the unencrypted EFI System Partition (readable even when the OS volume is
            //    locked). PRODUCT TODO: escrow to SilverSync + show it in the wizard's Done step.
            "if (-not ((Get-BitLockerVolume -MountPoint $mp).KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' })) { ",
            "Add-BitLockerKeyProtector -MountPoint $mp -RecoveryPasswordProtector | Out-Null }; ",
            "$rp=((Get-BitLockerVolume -MountPoint $mp).KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } | Select-Object -First 1).RecoveryPassword; ",
            "if ($rp) { New-Item -ItemType Directory -Force 'C:\\ProgramData\\SilverMetal' | Out-Null; ",
            "Set-Content -Path 'C:\\ProgramData\\SilverMetal\\bitlocker-recovery.txt' -Value $rp; ",
            "try { mountvol Q: /S; Set-Content -Path 'Q:\\SilverMetal-Recovery.txt' -Value $rp; mountvol Q: /D } catch {} }; ",
            // Outcome check: fail loudly (non-zero exit) if a TPM+PIN protector is not present at
            // the end — this is what actually matters (a benign non-terminating warning alone
            // must not pass, and a real failure must not stay silent).
            "$ok=(Get-BitLockerVolume -MountPoint $mp).KeyProtector | Where-Object { $_.KeyProtectorType -eq 'TpmPin' }; ",
            "if (-not $ok) { Write-Error 'TPM+PIN protector not present after enrollment'; exit 1 }");

        var r = await runner.RunAsync("powershell.exe",
            $"-NoProfile -ExecutionPolicy Bypass -Command \"{script}\"", ct);
        r.EnsureSuccess("BitLocker enrollment");
    }
}
