#include "wallet_security_controller.h"
#include "../util/secure_vault.h"

#include <cctype>
#include <cstdio>
#include <utility>

namespace dragonx {
namespace services {

WalletSecurityController::~WalletSecurityController()
{
    clearDeferredEncryption();
}

void WalletSecurityController::beginDeferredEncryption(std::string passphrase, std::string pin)
{
    clearDeferredEncryption();
    deferred_.passphrase = std::move(passphrase);
    deferred_.pin = std::move(pin);
    deferred_.pending = true;
    deferred_.lastConnectAttempt = -10.0;
}

WalletSecurityController::DeferredEncryptionSnapshot WalletSecurityController::deferredEncryption() const
{
    return {deferred_.passphrase, deferred_.pin};
}

bool WalletSecurityController::shouldAttemptDeferredConnect(double nowSeconds, double minIntervalSeconds)
{
    if (!deferred_.pending) return false;
    if (nowSeconds - deferred_.lastConnectAttempt < minIntervalSeconds) return false;
    deferred_.lastConnectAttempt = nowSeconds;
    return true;
}

void WalletSecurityController::clearDeferredEncryption()
{
    secureClear(deferred_.passphrase);
    secureClear(deferred_.pin);
    deferred_.pending = false;
    deferred_.lastConnectAttempt = -10.0;
}

WalletSecurityController::DeferredEncryptionResult WalletSecurityController::runDeferredEncryption(
    DeferredEncryptionSnapshot request, RpcGateway& rpc, VaultGateway* vault)
{
    DeferredEncryptionResult result;
    result.pinProvided = !request.pin.empty();

    std::string error;
    if (!rpc.encryptWallet(request.passphrase, error)) {
        result.error = error.empty() ? "encryptwallet failed" : error;
        secureClear(request.passphrase);
        secureClear(request.pin);
        return result;
    }

    result.encrypted = true;
    result.restartRequired = true;
    if (result.pinProvided && vault) {
        result.pinStored = vault->storePin(request.pin, request.passphrase);
    }

    secureClear(request.passphrase);
    secureClear(request.pin);
    return result;
}

WalletSecurityController::PinValidationResult WalletSecurityController::validatePinSetup(
    const std::string& pin, const std::string& confirmation, bool allowEmpty, std::size_t minLength)
{
    if (pin.empty() && confirmation.empty()) {
        return allowEmpty
            ? PinValidationResult{true, PinValidationError::None, ""}
            : PinValidationResult{false, PinValidationError::Empty, "PIN is required"};
    }
    if (pin != confirmation) {
        return {false, PinValidationError::Mismatch, "PINs do not match"};
    }
    if (pin.size() < minLength) {
        return {false, PinValidationError::TooShort, "PIN is too short"};
    }
    for (unsigned char c : pin) {
        if (!std::isdigit(c)) {
            return {false, PinValidationError::NonDigit, "PIN must contain only digits"};
        }
    }
    return {true, PinValidationError::None, ""};
}

WalletSecurityController::KeyKind WalletSecurityController::classifyAddress(const std::string& address)
{
    return !address.empty() && address[0] == 'z' ? KeyKind::Shielded : KeyKind::Transparent;
}

WalletSecurityController::KeyKind WalletSecurityController::classifyPrivateKey(const std::string& key)
{
    return !key.empty() && key[0] == 's' ? KeyKind::Shielded : KeyKind::Transparent;
}

const char* WalletSecurityController::importSuccessMessage(KeyKind kind)
{
    return kind == KeyKind::Shielded
        ? "Z-address key imported successfully. Wallet is rescanning."
        : "T-address key imported successfully. Wallet is rescanning.";
}

std::string WalletSecurityController::decryptExportFileName(std::uint64_t timestampSeconds)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "obsidiandecryptexport%llu",
             static_cast<unsigned long long>(timestampSeconds));
    return std::string(buffer);
}

void WalletSecurityController::secureClear(std::string& value)
{
    if (!value.empty()) {
        util::SecureVault::secureZero(&value[0], value.size());
        value.clear();
    }
}

} // namespace services
} // namespace dragonx
