using Moq;
using SilverOS.Welcome.Core.Apply;

public class ApplyServicesTests
{
    private static Mock<IProcessRunner> Ok()
    {
        var m = new Mock<IProcessRunner>();
        m.Setup(r => r.RunAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(new ProcessResult(0, "", ""));
        return m;
    }

    private static Mock<IProcessRunner> Fail()
    {
        var m = new Mock<IProcessRunner>();
        m.Setup(r => r.RunAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(new ProcessResult(1, "", "the operation failed"));
        return m;
    }

    [Fact]
    public async Task BitLockerService_throws_on_nonzero_exit()
    {
        await Assert.ThrowsAsync<InvalidOperationException>(() =>
            new BitLockerService(Fail().Object).EnableAsync("123456"));
    }

    [Fact]
    public async Task BitLockerService_enables_tpm_and_pin()
    {
        var run = Ok();
        await new BitLockerService(run.Object).EnableAsync("123456");
        run.Verify(r => r.RunAsync("powershell.exe", It.Is<string>(s =>
            s.Contains("Enable-BitLocker") && s.Contains("TpmAndPinProtector")), It.IsAny<CancellationToken>()));
    }

    [Fact]
    public async Task BitLockerService_sets_fve_pin_policy_and_strips_tpm_only_protector()
    {
        var run = Ok();
        await new BitLockerService(run.Object).EnableAsync("123456");
        // Sets the FVE "require additional authentication at startup" policy so the
        // TPM+PIN protector actually applies (otherwise it silently degrades to TPM-only).
        run.Verify(r => r.RunAsync("powershell.exe", It.Is<string>(s =>
            s.Contains("UseAdvancedStartup") && s.Contains("UseTPMPIN")), It.IsAny<CancellationToken>()));
        // Handles a volume already encrypted by Windows auto-device-encryption (TPM-only)
        // by adding the TPM+PIN protector instead of failing.
        run.Verify(r => r.RunAsync("powershell.exe", It.Is<string>(s =>
            s.Contains("Add-BitLockerKeyProtector")), It.IsAny<CancellationToken>()));
        // Removes any TPM-only protector so the device requires the PIN at pre-boot.
        run.Verify(r => r.RunAsync("powershell.exe", It.Is<string>(s =>
            s.Contains("Remove-BitLockerKeyProtector")), It.IsAny<CancellationToken>()));
        // Ejects optical install media first (BitLocker refuses to enroll with bootable media present).
        run.Verify(r => r.RunAsync("powershell.exe", It.Is<string>(s =>
            s.Contains("Shell.Application") && s.Contains("Eject")), It.IsAny<CancellationToken>()));
    }
}
