#include <electricity/logger/database.hpp>
#include <exception>
#include <iomanip>
#include <spdlog/spdlog.h>
#include <sstream>
#include <util/date.hpp>

sqlite3 * OpenDatabase(std::string const & databaseFilePath)
{
    sqlite3 * connectionPtr;
    if(sqlite3_open(databaseFilePath.c_str(), &connectionPtr) != SQLITE_OK)
    {
        throw std::runtime_error("Error opening SQLite3 database");
    }
    sqlite3_extended_result_codes(connectionPtr, 1);

    return connectionPtr;
}

std::string ToSqlInsertStatement(DSMR::Data const & data, time_t const time)
{
    std::stringstream ss;
    ss << "INSERT INTO ElectricityLog VALUES('" << Util::GetSqliteDate(time) << "','" << Util::GetSqliteUtcTime(time)
       << "'," << std::fixed << std::setprecision(2) << data.currentPowerUsageKw << ','
       << data.totalPowerConsumptionDayKwh << ',' << data.totalPowerConsumptionNightKwh << ','
       << data.currentPowerReturnKw << ',' << data.totalPowerReturnedDayKwh << ',' << data.totalPowerReturnedNightKwh
       << ',' << data.usingDayTarif << ',' << data.gasConsumptionCubicMeters << ");";

    return ss.str();
}

void Database::Insert(DSMR::Data const & data, time_t const time)
{
    std::stringstream transaction;
    transaction << "BEGIN TRANSACTION;" << ToSqlInsertStatement(data, time) << "COMMIT;";

    if(sqlite3_exec(connectionPtr, transaction.str().c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
    {
        spdlog::error("Failed to insert DSMR record into SQLite database: {}", sqlite3_errmsg(connectionPtr));
        throw std::runtime_error("Failed to insert DSMR record into SQLite databas");
    }
}

Database::Database(std::string const & databaseFilePath)
{
    if(sqlite3_open(databaseFilePath.c_str(), &connectionPtr) != SQLITE_OK)
    {
        spdlog::error("Error whilst opening SQLite database {}", databaseFilePath);
        throw std::runtime_error("Error opening SQLite3 database");
    }
    sqlite3_extended_result_codes(connectionPtr, 1);
}

Database::~Database()
{
    if(connectionPtr)
    {
        sqlite3_close(connectionPtr);
    }
}
