// SPDX-FileCopyrightText: 2025 Slatian
//
// SPDX-License-Identifier: LGPL-3.0-only

use crate::rusqlite::AssemblyContext;
use crate::rusqlite::InvertableRusqliteQuery;
use crate::rusqlite::RusqliteQuery;
use crate::sql::Field;

/// Turns criteria into queries for rusqlite.
///
/// This is the fallible version of [AssembleRusqliteQuery][crate::rusqlite::AssembleRusqliteQuery].
/// See its documentation on details of how to use this trait.
pub trait TryAssembleRusqliteQuery<F: Field, C> {
	/// The error type that will report failure modes of this assbler implementation.
	type Error;

	/// Uses knowlege from the implementation and the provided context to
	/// assemble a rusqlite query.
	///
	/// Fallible cousin of [assemble_rusqlite_query][super::AssembleRusqliteQuery::assemble_rusqlite_query].
	fn try_assemble_rusqlite_query(
		&self,
		assembly_context: &AssemblyContext,
		user_context: &C,
	) -> Result<InvertableRusqliteQuery<F>, Self::Error>;

	/// Like `try_assemble_rusqlite_query`, but resolves any dangling
	/// inversion optimizations.
	///
	/// Fallible cousin of [assemble_finished_rusqlite_query][super::AssembleRusqliteQuery::assemble_finished_rusqlite_query].
	fn try_assemble_finished_rusqlite_query(
		&self,
		assembly_context: &AssemblyContext,
		user_context: &C,
	) -> Result<RusqliteQuery<F>, Self::Error> {
		Ok(self
			.try_assemble_rusqlite_query(assembly_context, user_context)?
			.get_corrected_query())
	}

	/// Stripped down version of the assembly function intended to be called
	/// from database code to get the query generation started.
	///
	/// Fallible cousin of [assemble_rusqlite_query_for_db][super::AssembleRusqliteQuery::assemble_rusqlite_query_for_db].
	fn try_assemble_rusqlite_query_for_db(
		&self,
		user_context: &C,
	) -> Result<RusqliteQuery<F>, Self::Error> {
		self.try_assemble_finished_rusqlite_query(&AssemblyContext::new_root(), user_context)
	}
}
