#pragma once

#include <cstdint>
#include <map>
#include <string>
#include <vector>

struct sqlite3;

namespace dragonx {
namespace ui {

struct ExplorerBlockSummary {
    int height = 0;
    std::string hash;
    int tx_count = 0;
    int size = 0;
    std::int64_t time = 0;
    double difficulty = 0.0;
};

class ExplorerBlockCache {
public:
    struct SavedTipValidation {
        bool needed = false;
        int height = 0;
        std::string expectedHash;
    };

    ExplorerBlockCache();
    ExplorerBlockCache(std::string databasePath, std::string legacyJsonPath);
    ~ExplorerBlockCache();

    ExplorerBlockCache(const ExplorerBlockCache&) = delete;
    ExplorerBlockCache& operator=(const ExplorerBlockCache&) = delete;

    static std::string defaultDatabasePath();
    static std::string defaultLegacyJsonPath();

    bool ensureOpen();
    bool isOpen() const { return db_ != nullptr; }
    const std::string& databasePath() const { return database_path_; }

    std::map<int, ExplorerBlockSummary> loadRange(int minHeight, int maxHeight);
    // Fuzzy search over cached blocks: matches when the query is a substring of the height (as text)
    // or the block hash (case-insensitive). Returns newest-first, capped at `limit`.
    std::vector<ExplorerBlockSummary> searchBlocks(const std::string& query, int limit);
    bool storeBlock(const ExplorerBlockSummary& block);
    int cachedBlockCount();
    void clearBlocks();

    SavedTipValidation prepareValidation(int currentHeight, const std::string& currentBestHash);
    void applySavedTipValidation(const SavedTipValidation& validation,
                                 const std::string& actualHash,
                                 int currentHeight,
                                 const std::string& currentBestHash);
    void updateTip(int height, const std::string& hash);

private:
    bool exec(const char* sql);
    std::string getMetaValue(const std::string& key);
    int getMetaInt(const std::string& key, int fallback);
    void setMetaValue(const std::string& key, const std::string& value);
    bool createSchema();
    void migrateLegacyJsonIfNeeded();
    void close();

    sqlite3* db_ = nullptr;
    std::string database_path_;
    std::string legacy_json_path_;
};

} // namespace ui
} // namespace dragonx
