#ifndef DATABASEMANAGER_H
#define DATABASEMANAGER_H

#include <QObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QString>
#include <QList>
#include <QPair>
#include <QThread>
#include <QMap>
#include <QMutex>
#include <QWaitCondition>

#include <QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>
#include <QRegularExpression>

/**
 * @brief The DatabaseManager class handles all database operations
 * for the screenshot gallery application.
 */
class DatabaseManager : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief Struct to represent an image item with its path and OCR text
     */
    struct ImageItem {
        QString filePath;
        QString ocrText;
        int id; // Add id to support pagination
    };

    /**
     * @brief DatabaseManager constructor
     * @param parent The parent QObject
     */
    explicit DatabaseManager(QObject *parent = nullptr);
    
    /**
     * @brief DatabaseManager destructor
     */
    ~DatabaseManager();

    /**
     * @brief Initialize the database connection
     * @param dbPath Path to the SQLite database
     * @return True if connection was successful, false otherwise
     */
    bool initialize(const QString &dbPath);

    /**
     * @brief Create a new empty database with the required schema at the given path.
     *        The parent directory must already exist.
     * @param dbPath Path where the SQLite database should be created
     * @return True if creation was successful, false otherwise
     */
    static bool createDatabase(const QString &dbPath);

    /**
     * @brief Get all images from the database with pagination
     * @param offset Starting position (0-based) for pagination
     * @param limit Maximum number of items to return, 0 means no limit
     * @return List of ImageItem objects
     */
    QList<ImageItem> getAllImages(int offset = 0, int limit = 0);

    /**
     * @brief Get total count of all images in the database
     * @return Total number of images
     */
    int getImageCount();

public slots:
    /**
     * @brief Search for images matching the search text
     * @param searchText Text to search for in OCR results
     * @param offset Starting position (0-based) for pagination
     * @param limit Maximum number of items to return, 0 means no limit
     */
    void searchImages(const QString &searchText, int offset = 0, int limit = 0);

    /**
     * @brief Cancel any ongoing search operations
     */
    void cancelSearch();

signals:
    /**
     * @brief Signal emitted when search results are available
     * @param results The list of image items matching the search
     * @param searchText The original search text that produced these results
     * @param offset The offset used for this result set
     * @param limit The limit used for this result set
     * @param totalCount The total number of results matching the search (regardless of pagination)
     */
    void searchResultsReady(const QList<DatabaseManager::ImageItem> &results, const QString &searchText, 
                           int offset, int limit, int totalCount);

    /**
     * @brief Signal emitted when search operation starts
     * @param searchText The search text being processed
     */
    void searchStarted(const QString &searchText);

private:
    QSqlDatabase m_db;
    bool m_initialized;
    bool m_ftsEnabled;  // Whether FTS5 is available and enabled
    
    // Cache for search results to improve response time
    // Cache structure includes both results and total count
    struct SearchCacheItem {
        QList<ImageItem> results;
        int totalCount;
        QDateTime timestamp;
    };
    
    QMap<QString, QMap<QPair<int, int>, SearchCacheItem>> m_searchCache; // searchText -> {(offset, limit) -> results}
    QMutex m_cacheMutex;  // Mutex to protect cache access from multiple threads
    
    // All images cache with pagination
    QMap<QPair<int, int>, QList<ImageItem>> m_allImagesCache; // (offset, limit) -> results
    int m_cachedImageCount; // Total image count cache
    QDateTime m_lastCacheUpdate; // When the cache was last updated
    
    // Search thread management
    QFuture<void> m_searchFuture;
    QFutureWatcher<void> m_searchWatcher;
    QString m_currentSearchText;
    int m_currentOffset;
    int m_currentLimit;
    bool m_searchCancelled;
    QMutex m_searchMutex;
    
    // Cache settings
    static const int MAX_CACHE_SIZE = 50;        // Maximum number of cached search queries
    static const int DEFAULT_PAGE_SIZE = 100;    // Default number of items per page
    static const int CACHE_LIFETIME_SECS = 300;  // Cache lifetime in seconds (5 minutes)
    

    
    // Initialize FTS5 full-text search
    bool initializeFTS();
    
    // Prepare FTS query with proper syntax
    QString prepareFTSQuery(const QString &searchText);
    
    // Perform search operation in background thread
    void performSearchInBackground(const QString &searchText, int offset, int limit);
    
    // Clear expired cache items
    void cleanupCache();
    
    // Get a database connection for the current thread
    QSqlDatabase getDatabaseConnection();
};

#endif // DATABASEMANAGER_H