#pragma once

#include <cstddef>
#include <cstdint>
#include <string>

namespace dragonx {
namespace services {

class WalletSecurityController {
public:
    enum class PinValidationError {
        None,
        Empty,
        Mismatch,
        TooShort,
        NonDigit
    };

    struct PinValidationResult {
        bool ok = false;
        PinValidationError error = PinValidationError::None;
        const char* message = "";
    };

    struct DeferredEncryptionSnapshot {
        std::string passphrase;
        std::string pin;
    };

    class RpcGateway {
    public:
        virtual ~RpcGateway() = default;
        virtual bool encryptWallet(const std::string& passphrase, std::string& error) = 0;
        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 importWallet(const std::string& filePath, long timeoutSeconds, std::string& error) = 0;
    };

    class VaultGateway {
    public:
        virtual ~VaultGateway() = default;
        virtual bool storePin(const std::string& pin, const std::string& passphrase) = 0;
    };

    enum class KeyKind {
        Transparent,
        Shielded
    };

    struct DeferredEncryptionResult {
        bool encrypted = false;
        bool pinProvided = false;
        bool pinStored = false;
        bool restartRequired = false;
        std::string error;
    };

    ~WalletSecurityController();

    void beginDeferredEncryption(std::string passphrase, std::string pin = {});
    bool hasDeferredEncryption() const { return deferred_.pending; }
    DeferredEncryptionSnapshot deferredEncryption() const;
    bool shouldAttemptDeferredConnect(double nowSeconds, double minIntervalSeconds = 3.0);
    void clearDeferredEncryption();

    DeferredEncryptionResult runDeferredEncryption(DeferredEncryptionSnapshot request,
                                                   RpcGateway& rpc,
                                                   VaultGateway* vault);

    static PinValidationResult validatePinSetup(const std::string& pin,
                                                const std::string& confirmation,
                                                bool allowEmpty = false,
                                                std::size_t minLength = 4);
    static KeyKind classifyAddress(const std::string& address);
    static KeyKind classifyPrivateKey(const std::string& key);
    // True if `key` is a shielded viewing key (Sapling incoming viewing key, "zivks…" — watch-only).
    static bool isViewingKey(const std::string& key);
    // True if `key` looks like a recognized Z (Sapling/Sprout spending) or T (WIF) private key.
    static bool isRecognizedPrivateKey(const std::string& key);
    // As above, but also accepts a recognized shielded viewing key — the import dialog auto-detects
    // both, so this is the single source of truth for its indicator AND its submit guard.
    static bool isRecognizedImportKey(const std::string& key);
    static const char* importSuccessMessage(KeyKind kind);
    static std::string decryptExportFileName(std::uint64_t timestampSeconds);
    static void secureClear(std::string& value);

private:
    struct DeferredEncryptionState {
        std::string passphrase;
        std::string pin;
        bool pending = false;
        double lastConnectAttempt = -10.0;
    };

    DeferredEncryptionState deferred_;
};

} // namespace services
} // namespace dragonx
