using Spectre.Console;
using ZB.MOM.WW.Secrets.Cli.Interactive.Flows;

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

/// <summary>
/// Composition root for the interactive console: the non-TTY gate that decides whether a bare
/// <c>secret</c> invocation launches the console, and the default wiring (flow set, recents store,
/// target reader, session factory) that <see cref="Program"/> hands to an <see cref="InteractiveShell"/>.
/// </summary>
public static class InteractiveEntry
{
    /// <summary>
    /// Whether a bare <c>secret</c> invocation should launch the interactive console. True only when no
    /// verb was supplied AND neither standard stream is redirected — a redirected stdin/stdout means the
    /// invocation is scripted/piped, where the console's prompts would hang or corrupt the pipe, so the
    /// caller falls through to headless usage instead.
    /// </summary>
    /// <param name="args">The process command-line arguments.</param>
    /// <param name="inputRedirected"><see cref="Console.IsInputRedirected"/> at process start.</param>
    /// <param name="outputRedirected"><see cref="Console.IsOutputRedirected"/> at process start.</param>
    public static bool ShouldEnterInteractive(string[] args, bool inputRedirected, bool outputRedirected)
        => args.Length == 0 && !inputRedirected && !outputRedirected;

    /// <summary>
    /// Builds the ordered flow set the shell is wired with — one instance of each menu action, in the
    /// order they appear on the menu. Exposed (and used by <see cref="CreateShell"/>) so the composition
    /// is assertable without running the shell.
    /// </summary>
    public static IReadOnlyList<IInteractiveFlow> CreateFlows() =>
    [
        new ListSecretsFlow(),
        new SetSecretFlow(),
        new RevealSecretFlow(),
        new DeleteSecretFlow(),
        new ReferenceAuditFlow(),
        new KekDoctorFlow(),
        new BundleExportFlow(),
        new BundleImportFlow(),
    ];

    /// <summary>
    /// Wires an <see cref="InteractiveShell"/> with its default collaborators: a per-user recents store
    /// under <c>~/.zb-secrets/recent-targets.json</c>, the target-config reader, the session factory, and
    /// <see cref="CreateFlows"/>. The shell's own ctor re-validates flow-title uniqueness.
    /// </summary>
    /// <param name="console">The console surface the shell (and its flows) render to.</param>
    public static InteractiveShell CreateShell(IAnsiConsole console)
    {
        string recentsPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
            ".zb-secrets",
            "recent-targets.json");

        return new InteractiveShell(
            console,
            new RecentTargetsStore(recentsPath),
            new TargetConfigReader(),
            new SecretsSessionFactory(),
            CreateFlows());
    }
}
