import { TRPCError } from "@trpc/server";
import type { AnnunciId } from "~/schemas/public/Annunci";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type {
	NewServizio,
	ServizioServizioId,
	ServizioUpdate,
} from "~/schemas/public/Servizio";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import { db } from "../db";

export const addServizio = async (data: NewServizio) => {
	try {
		return await db.transaction().execute(async (tx) => {
			const servizio = await tx
				.insertInto("servizio")
				.values(data)
				.returningAll()
				.executeTakeFirstOrThrow(
					() => new Error("Failed to insert new servizio into database"),
				);

			const acconto = await db
				.selectFrom("prezziario")
				.selectAll()
				.where("isActive", "=", true)
				.where("order_type", "=", OrderTypeEnum.Acconto)
				.where("service_type", "=", data.tipologia)
				.limit(1)
				.executeTakeFirst();

			if (!acconto) {
				throw new Error("Acconto not found for new servizio");
			}
			await tx
				.insertInto("ordini")
				.values({
					servizio_id: servizio.servizio_id,
					userid: servizio.user_id,
					type: OrderTypeEnum.Acconto,
					amount_cent: acconto.prezzo_cent,
					packid: acconto.idprezziario,
					isActive: false,
				})
				.execute();
			return servizio;
		});
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error adding new servizio: ${(e as Error).message}`,
		});
	}
};

export const getServizioById = async (servizioId: ServizioServizioId) => {
	try {
		return await db
			.selectFrom("servizio")
			.selectAll()
			.where("servizio_id", "=", servizioId)
			.executeTakeFirstOrThrow(
				() => new Error(`Servizio not found - servizioId: ${servizioId}`),
			);
	} catch (e) {
		throw new TRPCError({
			code: "NOT_FOUND",
			message: `Servizio not found - servizioId: ${servizioId}: ${(e as Error).message}`,
		});
	}
};

export const updateServizio = async ({
	servizioId,
	data,
}: {
	servizioId: ServizioServizioId;
	data: ServizioUpdate;
}) => {
	try {
		return await db
			.updateTable("servizio")
			.set(data)
			.where("servizio_id", "=", servizioId)
			.returningAll()
			.executeTakeFirstOrThrow(
				() =>
					new Error(`Failed to update servizio - servizioId: ${servizioId}`),
			);
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error updating servizio - servizioId: ${servizioId}: ${(e as Error).message}`,
		});
	}
};

export const deleteServizio = async (servizioId: ServizioServizioId) => {
	try {
		await db
			.deleteFrom("servizio")
			.where("servizio_id", "=", servizioId)
			.execute();
		return true;
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error deleting servizio - servizioId: ${servizioId}: ${(e as Error).message}`,
		});
	}
};

////// SERVIZIO ANNUNCI

export const getServizioAnnuncio = async ({
	servizioId,
	annuncioId,
}: {
	servizioId: ServizioServizioId;
	annuncioId: AnnunciId;
}) => {
	try {
		return await db
			.selectFrom("servizio_annunci")
			.selectAll()
			.where("servizio_id", "=", servizioId)
			.where("annunci_id", "=", annuncioId)
			.executeTakeFirstOrThrow(
				() =>
					new Error(
						`Servizio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}`,
					),
			);
	} catch (e) {
		throw new TRPCError({
			code: "NOT_FOUND",
			message: `Servizio not found - servizioId: ${servizioId}, annunciId: ${annuncioId}: ${(e as Error).message}`,
		});
	}
};

export const updateServizioAnnuncio = async ({
	servizioId,
	annuncioId,
	data,
}: {
	servizioId: ServizioServizioId;
	annuncioId: AnnunciId;
	data: ServizioAnnunciUpdate;
}) => {
	try {
		await db
			.updateTable("servizio_annunci")
			.set(data)
			.where("servizio_id", "=", servizioId)
			.where("annunci_id", "=", annuncioId)
			.execute();

		return true;
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error updating servizio from annuncio - servizioId: ${servizioId}, annunciId: ${annuncioId}: ${(e as Error).message}`,
		});
	}
};

export const deleteServizioAnnuncio = async (
	servizioId: ServizioServizioId,
	annuncioId: AnnunciId,
) => {
	try {
		await db
			.deleteFrom("servizio_annunci")
			.where("servizio_id", "=", servizioId)
			.where("annunci_id", "=", annuncioId)
			.execute();
		return true;
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error deleting servizio from annuncio - servizioId: ${servizioId}, annunciId: ${annuncioId}: ${(e as Error).message}`,
		});
	}
};
