import { db } from "@dokploy/server/db";
import {
	type apiCreateCustom,
	type apiCreateDiscord,
	type apiCreateEmail,
	type apiCreateGotify,
	type apiCreateLark,
	type apiCreateMattermost,
	type apiCreateNtfy,
	type apiCreatePushover,
	type apiCreateResend,
	type apiCreateSlack,
	type apiCreateTeams,
	type apiCreateTelegram,
	type apiUpdateCustom,
	type apiUpdateDiscord,
	type apiUpdateEmail,
	type apiUpdateGotify,
	type apiUpdateLark,
	type apiUpdateMattermost,
	type apiUpdateNtfy,
	type apiUpdatePushover,
	type apiUpdateResend,
	type apiUpdateSlack,
	type apiUpdateTeams,
	type apiUpdateTelegram,
	custom,
	discord,
	email,
	gotify,
	lark,
	mattermost,
	notifications,
	ntfy,
	pushover,
	resend,
	slack,
	teams,
	telegram,
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import type { z } from "zod";

export type Notification = typeof notifications.$inferSelect;

export const createSlackNotification = async (
	input: z.infer<typeof apiCreateSlack>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newSlack = await tx
			.insert(slack)
			.values({
				channel: input.channel,
				webhookUrl: input.webhookUrl,
			})
			.returning()
			.then((value) => value[0]);

		if (!newSlack) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting slack",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				slackId: newSlack.slackId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "slack",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateSlackNotification = async (
	input: z.infer<typeof apiUpdateSlack>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(slack)
			.set({
				channel: input.channel,
				webhookUrl: input.webhookUrl,
			})
			.where(eq(slack.slackId, input.slackId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createTelegramNotification = async (
	input: z.infer<typeof apiCreateTelegram>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newTelegram = await tx
			.insert(telegram)
			.values({
				botToken: input.botToken,
				chatId: input.chatId,
				messageThreadId: input.messageThreadId,
			})
			.returning()
			.then((value) => value[0]);

		if (!newTelegram) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting telegram",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				telegramId: newTelegram.telegramId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "telegram",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateTelegramNotification = async (
	input: z.infer<typeof apiUpdateTelegram>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(telegram)
			.set({
				botToken: input.botToken,
				chatId: input.chatId,
				messageThreadId: input.messageThreadId,
			})
			.where(eq(telegram.telegramId, input.telegramId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createDiscordNotification = async (
	input: z.infer<typeof apiCreateDiscord>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newDiscord = await tx
			.insert(discord)
			.values({
				webhookUrl: input.webhookUrl,
				decoration: input.decoration,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDiscord) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting discord",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				discordId: newDiscord.discordId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "discord",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateDiscordNotification = async (
	input: z.infer<typeof apiUpdateDiscord>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(discord)
			.set({
				webhookUrl: input.webhookUrl,
				decoration: input.decoration,
			})
			.where(eq(discord.discordId, input.discordId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createEmailNotification = async (
	input: z.infer<typeof apiCreateEmail>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newEmail = await tx
			.insert(email)
			.values({
				smtpServer: input.smtpServer,
				smtpPort: input.smtpPort,
				username: input.username,
				password: input.password,
				fromAddress: input.fromAddress,
				toAddresses: input.toAddresses,
			})
			.returning()
			.then((value) => value[0]);

		if (!newEmail) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting email",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				emailId: newEmail.emailId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "email",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateEmailNotification = async (
	input: z.infer<typeof apiUpdateEmail>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(email)
			.set({
				smtpServer: input.smtpServer,
				smtpPort: input.smtpPort,
				username: input.username,
				password: input.password,
				fromAddress: input.fromAddress,
				toAddresses: input.toAddresses,
			})
			.where(eq(email.emailId, input.emailId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createResendNotification = async (
	input: z.infer<typeof apiCreateResend>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newResend = await tx
			.insert(resend)
			.values({
				apiKey: input.apiKey,
				fromAddress: input.fromAddress,
				toAddresses: input.toAddresses,
			})
			.returning()
			.then((value) => value[0]);

		if (!newResend) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting resend",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				resendId: newResend.resendId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "resend",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateResendNotification = async (
	input: z.infer<typeof apiUpdateResend>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(resend)
			.set({
				apiKey: input.apiKey,
				fromAddress: input.fromAddress,
				toAddresses: input.toAddresses,
			})
			.where(eq(resend.resendId, input.resendId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createGotifyNotification = async (
	input: z.infer<typeof apiCreateGotify>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newGotify = await tx
			.insert(gotify)
			.values({
				serverUrl: input.serverUrl,
				appToken: input.appToken,
				priority: input.priority,
				decoration: input.decoration,
			})
			.returning()
			.then((value) => value[0]);

		if (!newGotify) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting gotify",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				gotifyId: newGotify.gotifyId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "gotify",
				organizationId: organizationId,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateGotifyNotification = async (
	input: z.infer<typeof apiUpdateGotify>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(gotify)
			.set({
				serverUrl: input.serverUrl,
				appToken: input.appToken,
				priority: input.priority,
				decoration: input.decoration,
			})
			.where(eq(gotify.gotifyId, input.gotifyId));

		return newDestination;
	});
};

export const createNtfyNotification = async (
	input: z.infer<typeof apiCreateNtfy>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newNtfy = await tx
			.insert(ntfy)
			.values({
				serverUrl: input.serverUrl,
				topic: input.topic,
				accessToken: input.accessToken ?? null,
				priority: input.priority,
			})
			.returning()
			.then((value) => value[0]);

		if (!newNtfy) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting ntfy",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				ntfyId: newNtfy.ntfyId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "ntfy",
				organizationId: organizationId,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateNtfyNotification = async (
	input: z.infer<typeof apiUpdateNtfy>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(ntfy)
			.set({
				serverUrl: input.serverUrl,
				topic: input.topic,
				accessToken: input.accessToken ?? null,
				priority: input.priority,
			})
			.where(eq(ntfy.ntfyId, input.ntfyId));

		return newDestination;
	});
};

export const createCustomNotification = async (
	input: z.infer<typeof apiCreateCustom>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newCustom = await tx
			.insert(custom)
			.values({
				endpoint: input.endpoint,
				headers: input.headers,
			})
			.returning()
			.then((value) => value[0]);

		if (!newCustom) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting custom",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				customId: newCustom.customId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "custom",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateCustomNotification = async (
	input: z.infer<typeof apiUpdateCustom>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(custom)
			.set({
				endpoint: input.endpoint,
				headers: input.headers,
			})
			.where(eq(custom.customId, input.customId));

		return newDestination;
	});
};

export const findNotificationById = async (notificationId: string) => {
	const notification = await db.query.notifications.findFirst({
		where: eq(notifications.notificationId, notificationId),
		with: {
			slack: true,
			telegram: true,
			discord: true,
			email: true,
			resend: true,
			gotify: true,
			ntfy: true,
			mattermost: true,
			custom: true,
			lark: true,
			pushover: true,
			teams: true,
		},
	});
	if (!notification) {
		throw new TRPCError({
			code: "NOT_FOUND",
			message: "Notification not found",
		});
	}
	return notification;
};

export const removeNotificationById = async (notificationId: string) => {
	const result = await db
		.delete(notifications)
		.where(eq(notifications.notificationId, notificationId))
		.returning();

	return result[0];
};

export const createLarkNotification = async (
	input: z.infer<typeof apiCreateLark>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newLark = await tx
			.insert(lark)
			.values({
				webhookUrl: input.webhookUrl,
			})
			.returning()
			.then((value) => value[0]);

		if (!newLark) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting lark",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				larkId: newLark.larkId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "lark",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateLarkNotification = async (
	input: z.infer<typeof apiUpdateLark>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(lark)
			.set({
				webhookUrl: input.webhookUrl,
			})
			.where(eq(lark.larkId, input.larkId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createTeamsNotification = async (
	input: z.infer<typeof apiCreateTeams>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newTeams = await tx
			.insert(teams)
			.values({
				webhookUrl: input.webhookUrl,
			})
			.returning()
			.then((value) => value[0]);

		if (!newTeams) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting teams",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				teamsId: newTeams.teamsId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "teams",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateTeamsNotification = async (
	input: z.infer<typeof apiUpdateTeams>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(teams)
			.set({
				webhookUrl: input.webhookUrl,
			})
			.where(eq(teams.teamsId, input.teamsId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const updateNotificationById = async (
	notificationId: string,
	notificationData: Partial<Notification>,
) => {
	const result = await db
		.update(notifications)
		.set({
			...notificationData,
		})
		.where(eq(notifications.notificationId, notificationId))
		.returning();

	return result[0];
};

export const createMattermostNotification = async (
	input: z.infer<typeof apiCreateMattermost>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newMattermost = await tx
			.insert(mattermost)
			.values({
				webhookUrl: input.webhookUrl,
				channel: input.channel,
				username: input.username,
			})
			.returning()
			.then((value) => value[0]);

		if (!newMattermost) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting mattermost",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				mattermostId: newMattermost.mattermostId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				notificationType: "mattermost",
				organizationId: organizationId,
				serverThreshold: input.serverThreshold,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updateMattermostNotification = async (
	input: z.infer<typeof apiUpdateMattermost>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(mattermost)
			.set({
				webhookUrl: input.webhookUrl,
				channel: input.channel,
				username: input.username,
			})
			.where(eq(mattermost.mattermostId, input.mattermostId))
			.returning()
			.then((value) => value[0]);

		return newDestination;
	});
};

export const createPushoverNotification = async (
	input: z.infer<typeof apiCreatePushover>,
	organizationId: string,
) => {
	await db.transaction(async (tx) => {
		const newPushover = await tx
			.insert(pushover)
			.values({
				userKey: input.userKey,
				apiToken: input.apiToken,
				priority: input.priority,
				retry: input.retry,
				expire: input.expire,
			})
			.returning()
			.then((value) => value[0]);

		if (!newPushover) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting pushover",
			});
		}

		const newDestination = await tx
			.insert(notifications)
			.values({
				pushoverId: newPushover.pushoverId,
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				serverThreshold: input.serverThreshold,
				notificationType: "pushover",
				organizationId: organizationId,
			})
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error input: Inserting notification",
			});
		}

		return newDestination;
	});
};

export const updatePushoverNotification = async (
	input: z.infer<typeof apiUpdatePushover>,
) => {
	await db.transaction(async (tx) => {
		const newDestination = await tx
			.update(notifications)
			.set({
				name: input.name,
				appDeploy: input.appDeploy,
				appBuildError: input.appBuildError,
				databaseBackup: input.databaseBackup,
				dokployBackup: input.dokployBackup,
				volumeBackup: input.volumeBackup,
				dokployRestart: input.dokployRestart,
				dockerCleanup: input.dockerCleanup,
				organizationId: input.organizationId,
				serverThreshold: input.serverThreshold,
			})
			.where(eq(notifications.notificationId, input.notificationId))
			.returning()
			.then((value) => value[0]);

		if (!newDestination) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Error Updating notification",
			});
		}

		await tx
			.update(pushover)
			.set({
				userKey: input.userKey,
				apiToken: input.apiToken,
				priority: input.priority,
				retry: input.retry,
				expire: input.expire,
			})
			.where(eq(pushover.pushoverId, input.pushoverId));

		return newDestination;
	});
};
