import { TRPCError } from "@trpc/server";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type {
	NewPrezziario,
	Prezziario,
	PrezziarioIdprezziario,
	PrezziarioUpdate,
} from "~/schemas/public/Prezziario";
import type { TestiEStringheStingaId } from "~/schemas/public/TestiEStringhe";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { db, type Querier } from "~/server/db";

export const CONDIZIONI_DEFAULT = "CONDIZIONI_CERCHI" as TestiEStringheStingaId;
export const getPrezziario = async () => {
	try {
		return await db
			.selectFrom("prezziario")
			.selectAll()
			.where("isActive", "=", true)
			.orderBy("idprezziario", "asc")
			.execute();
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error getting prezziario: ${(error as Error).message}`,
		});
	}
};

export const getPrezziarioByIdHandler = async (id: PrezziarioIdprezziario) => {
	try {
		return await db
			.selectFrom("prezziario")
			.selectAll()
			.where("prezziario.idprezziario", "=", id)
			.executeTakeFirst();
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error getting prezziario by id: ${(error as Error).message}`,
		});
	}
};

export const addPrezziario = async ({
	db,
	input,
}: {
	db: Querier;
	input: NewPrezziario;
}): Promise<Prezziario> => {
	try {
		return await db
			.insertInto("prezziario")
			.values(input)
			.returningAll()
			.executeTakeFirstOrThrow(
				() => new Error(`Failed to add prezziario with name: ${input.nome_it}`),
			);
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error adding prezziario: ${(error as Error).message}`,
		});
	}
};
export const updatePrezziario = async ({
	db,
	prezziarioId,
	input,
}: {
	db: Querier;
	prezziarioId: PrezziarioIdprezziario;
	input: PrezziarioUpdate;
}): Promise<Prezziario> => {
	try {
		return await db
			.updateTable("prezziario")
			.set(input)
			.where("prezziario.idprezziario", "=", prezziarioId)
			.returningAll()
			.executeTakeFirstOrThrow(
				() => new Error(`Failed to update prezziario with id: ${prezziarioId}`),
			);
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error updating prezziario: ${(error as Error).message}`,
		});
	}
};

// export const deletePrezziario = async ({
// 	db,
// 	prezziarioId,
// }: {
// 	db: Querier;

// 	prezziarioId: PrezziarioIdprezziario;
// }): Promise<void> => {
// 	try {
// 		await db
// 			.deleteFrom("prezziario")
// 			.where("prezziario.idprezziario", "=", prezziarioId)
// 			.execute();
// 	} catch (error) {
// 		throw new TRPCError({
// 			code: "INTERNAL_SERVER_ERROR",
// 			message: `Error deleting prezziario: ${(error as Error).message}`,
// 		});
// 	}
// };

type MinimalPrezziario = Pick<
	Prezziario,
	"idprezziario" | "prezzo_cent" | "nome_it" | "nome_en" | "sconto"
>;
type PrezziarioByTipologia = {
	acconto: MinimalPrezziario;
	saldi: MinimalPrezziario[];
};

export const getPrezziarioByTipologia = async ({
	db,
	tipologia,
}: {
	db: Querier;
	tipologia: TipologiaPosizioneEnum;
}): Promise<PrezziarioByTipologia> => {
	try {
		const { acconto, saldi } = await db.transaction().execute(async (trx) => {
			const acconto = await trx
				.selectFrom("prezziario")
				.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
				.where("order_type", "=", OrderTypeEnum.Acconto)
				.where("service_type", "=", tipologia)
				.where("isActive", "=", true)
				.executeTakeFirst();

			if (!acconto) {
				throw new TRPCError({
					code: "NOT_FOUND",
					message: "Acconto not found",
				});
			}
			const saldi = await trx
				.selectFrom("prezziario")
				.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
				.where("order_type", "=", OrderTypeEnum.Saldo)
				.where("service_type", "=", tipologia)
				.where("isActive", "=", true)
				.orderBy("service_variant", "asc")

				.execute();

			if (!saldi) {
				throw new TRPCError({
					code: "NOT_FOUND",
					message: "Saldi not found",
				});
			}

			return { acconto, saldi };
		});

		return { acconto, saldi };
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error getting prezziario by tipologia: ${(error as Error).message}`,
		});
	}
};

export const getPrezziarioConsulenza = async ({ db }: { db: Querier }) => {
	try {
		return await db.transaction().execute(async (trx) => {
			const prezzi = await trx
				.selectFrom("prezziario")
				.select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
				.where("order_type", "=", OrderTypeEnum.Consulenza)
				.where("isActive", "=", true)
				.where("service_type", "=", TipologiaPosizioneEnum.Stabile)
				.orderBy("prezzo_cent", "asc")
				.execute();

			if (!prezzi || prezzi.length !== 3) {
				throw new TRPCError({
					code: "NOT_FOUND",
					message: "Consulenza prezzi not found",
				});
			}

			return prezzi;
		});
	} catch (error) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error getting prezziario by tipologia: ${(error as Error).message}`,
		});
	}
};
