using Spectre.Console;
using ZB.MOM.WW.Secrets.Abstractions;

namespace ZB.MOM.WW.Secrets.Cli.Interactive.Flows;

/// <summary>
/// Reveals a secret's decrypted plaintext on screen — the one flow whose purpose is to surface a value.
/// It gates the disclosure behind an explicit confirmation: on decline nothing is printed; on accept the
/// value is decrypted with the session cipher and written exactly once (no caching, no resolver). Requires
/// a KEK-capable session.
/// </summary>
public sealed class RevealSecretFlow : IInteractiveFlow
{
    /// <inheritdoc />
    public string Title => "Get (reveal) a secret";

    /// <inheritdoc />
    public bool RequiresKek => true;

    /// <inheritdoc />
    public async Task RunAsync(IAnsiConsole console, SecretsSession session, CancellationToken ct)
    {
        ArgumentNullException.ThrowIfNull(console);
        ArgumentNullException.ThrowIfNull(session);

        ISecretCipher cipher = session.Cipher
            ?? throw new InvalidOperationException("flow requires an unlocked KEK session");

        var name = new SecretName(console.Prompt(
            new TextPrompt<string>("Secret [green]name[/]:").Validate(FlowPrompts.ValidateSecretName)));

        StoredSecret? row = await session.Store.GetAsync(name, ct).ConfigureAwait(false);
        if (row is null || row.IsDeleted)
        {
            console.MarkupLineInterpolated($"[red]No secret named '{name.Value}'.[/]");
            return;
        }

        if (!console.Prompt(new ConfirmationPrompt("Reveal the value on screen?") { DefaultValue = false }))
        {
            return;
        }

        console.WriteLine(cipher.Decrypt(row));
    }
}
