/*
 * Copyright (C) 2022-2025 Seagull Developers
 *
 * Seagull is the legal property of its developers, whose names are too
 * numerous to list here. Please refer to the AUTHORS file distributed
 * with this source distribution
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#include <glib.h>

#include <sqlite3.h>

#include <seagull.h>

/******************************************************************************
 * Main
 *****************************************************************************/
static void
test_seagull_transaction_begin_commit(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	rc = sqlite3_open(":memory:", &db);
	g_assert_nonnull(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	result = seagull_transaction_begin(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);

	result = seagull_transaction_commit(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);

	rc = sqlite3_close(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);
}

static void
test_seagull_transaction_begin_rollback(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	rc = sqlite3_open(":memory:", &db);
	g_assert_nonnull(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	result = seagull_transaction_begin(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);

	result = seagull_transaction_rollback(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);

	rc = sqlite3_close(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);
}

static void
test_seagull_transaction_begin_begin(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	rc = sqlite3_open(":memory:", &db);
	g_assert_nonnull(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	result = seagull_transaction_begin(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);

	result = seagull_transaction_begin(db, &error);
	g_assert_error(error,
	               SEAGULL_TRANSACTION_ERROR,
	               SEAGULL_TRANSACTION_ERROR_BEGIN_FAILED);
	g_clear_error(&error);
	g_assert_false(result);

	rc = sqlite3_close(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);
}

static void
test_seagull_transaction_commit_without_begin(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	rc = sqlite3_open(":memory:", &db);
	g_assert_nonnull(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	result = seagull_transaction_commit(db, &error);
	g_assert_error(error,
	               SEAGULL_TRANSACTION_ERROR,
	               SEAGULL_TRANSACTION_ERROR_COMMIT_FAILED);
	g_clear_error(&error);
	g_assert_false(result);

	rc = sqlite3_close(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);
}

static void
test_seagull_transaction_rollback_without_begin(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	rc = sqlite3_open(":memory:", &db);
	g_assert_nonnull(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	result = seagull_transaction_rollback(db, &error);
	g_assert_error(error,
	               SEAGULL_TRANSACTION_ERROR,
	               SEAGULL_TRANSACTION_ERROR_ROLLBACK_FAILED);
	g_clear_error(&error);
	g_assert_false(result);

	rc = sqlite3_close(db);
	g_assert_cmpint(rc, ==, SQLITE_OK);
}

/******************************************************************************
 * Main
 *****************************************************************************/
int
main(int argc, char *argv[]) {
	g_test_init(&argc, &argv, NULL);

	g_test_add_func("/transaction/begin-commit",
	                test_seagull_transaction_begin_commit);
	g_test_add_func("/transaction/begin-rollback",
	                test_seagull_transaction_begin_rollback);
	g_test_add_func("/transaction/begin-begin",
	                test_seagull_transaction_begin_begin);

	g_test_add_func("/transaction/commit-without-begin",
	                test_seagull_transaction_commit_without_begin);
	g_test_add_func("/transaction/rollback-without-begin",
	                test_seagull_transaction_rollback_without_begin);

	return g_test_run();
}
