#ifndef DB_UTILS_H
#define DB_UTILS_H

#include "r.h"
#include <sqlite3.h>
#include <json-c/json.h>
#include "utils.h"




json_object* db_execute(const char *query);

char * db_file_expanded(){
    char * expanded = expand_home_directory(DB_FILE);
    static char result[4096];
    result[0] = 0;
    strcpy(result, expanded);
    free(expanded);
    return result;
}

void db_initialize();
json_object * db_set(const char *key, const char *value);
json_object* db_get(const char *key);
json_object* db_query(const char *query);


void db_initialize() {
    sqlite3 *db;
    char *err_msg = 0;
    int rc = sqlite3_open(db_file_expanded(), &db);

    if (rc != SQLITE_OK) {
        return;
    }

    const char *sql = "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);";
    rc = sqlite3_exec(db, sql, 0, 0, &err_msg);

    if (rc != SQLITE_OK) {
        sqlite3_free(err_msg);
    }

    sqlite3_close(db);
}


json_object * db_set(const char *key, const char *value) {
    sqlite3 *db;
    char *err_msg = 0;
    int rc = sqlite3_open(db_file_expanded(), &db);

    if (rc != SQLITE_OK) {
        return NULL;
    }

    char *sql = sqlite3_mprintf("INSERT INTO kv_store (key, value) VALUES (%Q, %Q) ON CONFLICT(key) DO UPDATE SET value = %Q WHERE key = %Q", key, value, value,key);
    rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
    sqlite3_free(sql);

    if (rc != SQLITE_OK) {
        sqlite3_free(err_msg);
        sqlite3_close(db);
        return NULL;
    }

    sqlite3_close(db);
    return json_object_new_string("Success");
}

json_object* db_get(const char *key) {
    sqlite3 *db;
    sqlite3_stmt *stmt;
    json_object *result = json_object_new_object();
    const char *value = NULL;

    int rc = sqlite3_open(db_file_expanded(), &db);
    if (rc != SQLITE_OK) {
        return NULL;
    }

    const char *sql = "SELECT value FROM kv_store WHERE key = ?";
    sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);

    if (sqlite3_step(stmt) == SQLITE_ROW) {
        value = (const char *)sqlite3_column_text(stmt, 0);
    }

    if (value) {
        json_object_object_add(result, "value", json_object_new_string(value));
    } else {
        json_object_object_add(result, "error", json_object_new_string("Key not found"));
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return result;
}
json_object* db_query(const char *query) {
    sqlite3 *db;
    sqlite3_stmt *stmt;

    if(strncmp(query, "SELECT", 6)){
        return db_execute(query);
    }

    json_object *result = json_object_new_array();

    int rc = sqlite3_open(db_file_expanded(), &db);
    if (rc != SQLITE_OK) {
        return NULL;
    }

    sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        json_object *row = json_object_new_object();
        for (int i = 0; i < sqlite3_column_count(stmt); i++) {
            const char *col_name = sqlite3_column_name(stmt, i);
            switch (sqlite3_column_type(stmt, i)) {
                case SQLITE_INTEGER:
                    json_object_object_add(row, col_name, json_object_new_int64(sqlite3_column_int64(stmt, i)));
                    break;
                case SQLITE_FLOAT:
                    json_object_object_add(row, col_name, json_object_new_double(sqlite3_column_double(stmt, i)));
                    break;
                case SQLITE_TEXT:
                    json_object_object_add(row, col_name, json_object_new_string((const char *)sqlite3_column_text(stmt, i)));
                    break;
                case SQLITE_BLOB:
                    json_object_object_add(row, col_name, json_object_new_string_len((const char *)sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i)));
                    break;
                case SQLITE_NULL:
                default:
                    json_object_object_add(row, col_name, json_object_new_string("NULL"));
                    break;
            }
        }
        json_object_array_add(result, row);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    return result;
}


json_object* db_execute(const char *query) {
    sqlite3 *db;
    char *err_msg = 0;
    int rc = sqlite3_open(db_file_expanded(), &db);
    json_object *result = json_object_new_object();

    if (rc != SQLITE_OK) {
        json_object_object_add(result, "error", json_object_new_string("Cannot open database"));
        return result;
    }

    rc = sqlite3_exec(db, query, 0, 0, &err_msg);
    if (rc != SQLITE_OK) {
        json_object_object_add(result, "error", json_object_new_string(err_msg));
        sqlite3_free(err_msg);
    } else {
        json_object_object_add(result, "success", json_object_new_string("Query executed successfully"));
    }

    sqlite3_close(db);
    return result;
}
char * db_get_schema(){
    json_object * tables =db_query("SELECT * FROM sqlite_master WHERE type='table'");
    char * result = strdup(json_object_get_string(tables));
    json_object_put(tables);
    return result;
}

#endif