#include "db.h"

#include <stdio.h>
#include <stdlib.h>

int odbc_succeeded(SQLRETURN ret) {
    return ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO;
}

void db_init(Db *db) {
    db->env = SQL_NULL_HENV;
    db->dbc = SQL_NULL_HDBC;
    db->connected = 0;
}

int db_connect(Db *db) {
    SQLRETURN ret;
    const char *env_conn = getenv("CGI_DB_CONN");
    SQLCHAR default_conn[] =
        "DRIVER={MariaDB};SERVER=localhost;DATABASE=sample;UID=user;PWD=pass;";
    SQLCHAR *conn = (SQLCHAR *)(env_conn != NULL ? env_conn : (char *)default_conn);

    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &db->env);
    if (!odbc_succeeded(ret)) {
        return 0;
    }

    ret = SQLSetEnvAttr(db->env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
    if (!odbc_succeeded(ret)) {
        return 0;
    }

    ret = SQLAllocHandle(SQL_HANDLE_DBC, db->env, &db->dbc);
    if (!odbc_succeeded(ret)) {
        return 0;
    }

    ret = SQLDriverConnect(db->dbc, NULL, conn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    if (!odbc_succeeded(ret)) {
        db_print_error(SQL_HANDLE_DBC, db->dbc);
        return 0;
    }

    db->connected = 1;
    return 1;
}

void db_close(Db *db) {
    if (db->dbc != SQL_NULL_HDBC) {
        if (db->connected) {
            SQLDisconnect(db->dbc);
        }
        SQLFreeHandle(SQL_HANDLE_DBC, db->dbc);
        db->dbc = SQL_NULL_HDBC;
    }
    if (db->env != SQL_NULL_HENV) {
        SQLFreeHandle(SQL_HANDLE_ENV, db->env);
        db->env = SQL_NULL_HENV;
    }
    db->connected = 0;
}

void db_print_error(SQLSMALLINT handle_type, SQLHANDLE handle) {
    SQLCHAR state[6];
    SQLINTEGER native_error;
    SQLCHAR message[256];
    SQLSMALLINT message_len;
    SQLRETURN ret = SQLGetDiagRec(
        handle_type,
        handle,
        1,
        state,
        &native_error,
        message,
        sizeof(message),
        &message_len
    );
    (void)native_error;
    (void)message_len;
    if (odbc_succeeded(ret)) {
        fprintf(stderr, "ODBC error [%s] %s\n", state, message);
    }
}
