#pragma once

#include "wallet_security_workflow.h"

#include <cstdint>
#include <functional>
#include <string>

namespace dragonx {
namespace services {

class WalletSecurityWorkflowExecutor {
public:
    using WalletFilePlan = WalletSecurityWorkflow::WalletFilePlan;

    struct Outcome {
        bool ok = false;
        std::string error;
        bool passphraseRejected = false;
    };

    struct ExportOutcome : Outcome {
        WalletFilePlan filePlan;
    };

    class RpcGateway {
    public:
        virtual ~RpcGateway() = default;
        virtual bool unlockWallet(const std::string& passphrase, int timeoutSeconds, std::string& error) = 0;
        virtual bool exportWallet(const std::string& fileName, long timeoutSeconds, std::string& error) = 0;
        virtual bool requestDaemonStop(std::string& error) = 0;
        virtual bool probeDaemon(std::string& error) = 0;
    };

    class ImportGateway {
    public:
        virtual ~ImportGateway() = default;
        virtual bool importWallet(const std::string& exportPath, long timeoutSeconds, std::string& error) = 0;
    };

    class FileGateway {
    public:
        virtual ~FileGateway() = default;
        virtual std::string dataDir() = 0;
        virtual bool backupEncryptedWallet(const WalletFilePlan& filePlan, std::string& error) = 0;
    };

    class DaemonGateway {
    public:
        virtual ~DaemonGateway() = default;
        virtual bool isUsingEmbeddedDaemon() const = 0;
        virtual void stopEmbeddedDaemon() = 0;
        virtual bool startEmbeddedDaemon() = 0;
        virtual bool cancelled() const = 0;
        virtual bool shuttingDown() const = 0;
        virtual void sleepForMs(int milliseconds) = 0;
    };

    using VaultCleanupGateway = std::function<void()>;

    static Outcome unlockWallet(const std::string& passphrase,
                                RpcGateway& rpc,
                                int timeoutSeconds = 600);
    static ExportOutcome exportWallet(RpcGateway& rpc,
                                      FileGateway& files,
                                      std::uint64_t timestampSeconds,
                                      long timeoutSeconds = 300L);
    static Outcome stopDaemon(RpcGateway& rpc);
    static Outcome backupEncryptedWallet(FileGateway& files,
                                         const WalletFilePlan& filePlan);
    static Outcome restartDaemonAndWait(DaemonGateway& daemon,
                                        RpcGateway& rpc,
                                        int preRestartDelayMs = 2000,
                                        int embeddedRestartSettleMs = 1000,
                                        int maxProbeSeconds = 60);
    static Outcome importWallet(ImportGateway& importer,
                                const std::string& exportPath,
                                long timeoutSeconds = 1200L);
    static void cleanupVaultAndPin(const VaultCleanupGateway& cleanup);
};

} // namespace services
} // namespace dragonx