#include "db/database.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define CREATE_SETTINGS_TABLE                                                  \
  "CREATE TABLE IF NOT EXISTS settings ("                                      \
  "key TEXT PRIMARY KEY, "                                                     \
  "value TEXT"                                                                 \
  ");"

sqlite3 *settings_init(const char *db_path) {
  sqlite3 *db = NULL;
  char *err_msg = NULL;

  // Open database
  int rc = sqlite3_open(db_path, &db);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return NULL;
  }

  // Create settings table if it doesn't exist
  rc = sqlite3_exec(db, CREATE_SETTINGS_TABLE, NULL, NULL, &err_msg);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "SQL error: %s\n", err_msg);
    sqlite3_free(err_msg);
    sqlite3_close(db);
    return NULL;
  }

  return db;
}

char *settings_get(sqlite3 *db, const char *key) {
  if (!db || !key) {
    return NULL;
  }

  sqlite3_stmt *stmt = NULL;
  const char *sql = "SELECT value FROM settings WHERE key = ?;";

  int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
    return NULL;
  }

  sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);

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

  sqlite3_finalize(stmt);
  return value;
}

int settings_set(sqlite3 *db, const char *key, const char *value) {
  if (!db || !key || !value) {
    return -1;
  }

  sqlite3_stmt *stmt = NULL;
  const char *sql =
      "INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?);";

  int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
    return -1;
  }

  // Use SQLITE_TRANSIENT to ensure SQLite makes its own copy of the strings
  sqlite3_bind_text(stmt, 1, key, -1, SQLITE_TRANSIENT);
  sqlite3_bind_text(stmt, 2, value, -1, SQLITE_TRANSIENT);

  rc = sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  return (rc == SQLITE_DONE) ? 0 : -1;
}

int settings_delete(sqlite3 *db, const char *key) {
  if (!db || !key) {
    return -1;
  }

  sqlite3_stmt *stmt = NULL;
  const char *sql = "DELETE FROM settings WHERE key = ?;";

  int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
    return -1;
  }

  sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);

  rc = sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  return (rc == SQLITE_DONE) ? 0 : -1;
}

void settings_close(sqlite3 *db) {
  if (db) {
    sqlite3_close(db);
  }
}
