#include "wallet_security_workflow_executor.h"

namespace dragonx {
namespace services {

WalletSecurityWorkflowExecutor::Outcome WalletSecurityWorkflowExecutor::unlockWallet(
    const std::string& passphrase, RpcGateway& rpc, int timeoutSeconds)
{
    std::string error;
    if (!rpc.unlockWallet(passphrase, timeoutSeconds, error)) {
        return {false, error.empty() ? "Incorrect passphrase" : error, true};
    }
    return {true, {}, false};
}

WalletSecurityWorkflowExecutor::ExportOutcome WalletSecurityWorkflowExecutor::exportWallet(
    RpcGateway& rpc, FileGateway& files, std::uint64_t timestampSeconds, long timeoutSeconds)
{
    ExportOutcome outcome;
    outcome.filePlan = WalletSecurityWorkflow::planWalletFiles(files.dataDir(), timestampSeconds);

    std::string error;
    if (!rpc.exportWallet(outcome.filePlan.exportFile, timeoutSeconds, error)) {
        outcome.ok = false;
        outcome.error = error.empty() ? "Export failed" : "Export failed: " + error;
        return outcome;
    }

    outcome.ok = true;
    return outcome;
}

WalletSecurityWorkflowExecutor::Outcome WalletSecurityWorkflowExecutor::stopDaemon(RpcGateway& rpc)
{
    std::string error;
    (void)rpc.requestDaemonStop(error);
    return {true, {}, false};
}

WalletSecurityWorkflowExecutor::Outcome WalletSecurityWorkflowExecutor::backupEncryptedWallet(
    FileGateway& files, const WalletFilePlan& filePlan)
{
    std::string error;
    if (!files.backupEncryptedWallet(filePlan, error)) {
        return {false, error.empty() ? "Failed to rename wallet.dat" : "Failed to rename wallet.dat: " + error, false};
    }
    return {true, {}, false};
}

WalletSecurityWorkflowExecutor::Outcome WalletSecurityWorkflowExecutor::restartDaemonAndWait(
    DaemonGateway& daemon, RpcGateway& rpc, int preRestartDelayMs,
    int embeddedRestartSettleMs, int maxProbeSeconds)
{
    auto waitForMs = [&](int milliseconds) -> bool {
        int remaining = milliseconds;
        while (remaining > 0 && !daemon.cancelled() && !daemon.shuttingDown()) {
            int slice = remaining >= 100 ? 100 : remaining;
            daemon.sleepForMs(slice);
            remaining -= slice;
        }
        return !daemon.cancelled() && !daemon.shuttingDown();
    };

    if (!waitForMs(preRestartDelayMs)) return {false, "", false};

    if (daemon.isUsingEmbeddedDaemon()) {
        daemon.stopEmbeddedDaemon();
        if (daemon.cancelled() || daemon.shuttingDown()) return {false, "", false};
        if (!waitForMs(embeddedRestartSettleMs)) return {false, "", false};
        daemon.startEmbeddedDaemon();
    }

    bool daemonUp = false;
    std::string lastError;
    for (int i = 0; i < maxProbeSeconds && !daemon.cancelled() && !daemon.shuttingDown(); ++i) {
        daemon.sleepForMs(1000);
        if (rpc.probeDaemon(lastError)) {
            daemonUp = true;
            break;
        }
    }

    if (daemon.cancelled() || daemon.shuttingDown()) return {false, "", false};
    if (!daemonUp) return {false, "Daemon failed to restart", false};
    return {true, {}, false};
}

WalletSecurityWorkflowExecutor::Outcome WalletSecurityWorkflowExecutor::importWallet(
    ImportGateway& importer, const std::string& exportPath, long timeoutSeconds)
{
    std::string error;
    if (!importer.importWallet(exportPath, timeoutSeconds, error)) {
        return {false, error.empty() ? "Key import failed" : "Key import failed: " + error, false};
    }
    return {true, {}, false};
}

void WalletSecurityWorkflowExecutor::cleanupVaultAndPin(const VaultCleanupGateway& cleanup)
{
    if (cleanup) cleanup();
}

} // namespace services
} // namespace dragonx