import { TRPCError } from "@trpc/server";
import { jsonArrayFrom } from "kysely/helpers/postgres";
import type { Etichette } from "~/schemas/public/Etichette";
import type { Users, UsersId, UsersUpdate } from "~/schemas/public/Users";
import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
import { db, type Querier } from "~/server/db";

export const editAccountHandler = async ({
	id,
	data,
}: {
	id: UsersId;
	data: UsersUpdate;
}) => {
	try {
		await db
			.updateTable("users")
			.set({
				...data,
			})
			.where("id", "=", id)
			.execute();

		return "success";
	} catch {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: "errore modifica utente",
		});
	}
};

export const editAnagraficaHandler = async ({
	userId,
	data,
}: {
	userId: UsersId;
	data: UsersAnagraficaUpdate;
}) => {
	try {
		const { idanagrafica, userid, ...rest } = data;
		if (!userId) {
			throw new TRPCError({
				code: "BAD_REQUEST",
				message: "Errore interno, utente non trovato",
			});
		}

		// if (anagraficaId) {
		// 	return await db
		// 		.updateTable("users_anagrafica")
		// 		.set({
		// 			...rest,
		// 		})
		// 		.where("userid", "=", userId)
		// 		.returningAll()
		// 		.executeTakeFirst();
		// }
		// const searched = await db
		// 	.selectFrom("users_anagrafica")
		// 	.select("idanagrafica")
		// 	.where("userid", "=", userId)
		// 	.executeTakeFirst();
		// if (searched) {
		// 	return await db
		// 		.updateTable("users_anagrafica")
		// 		.set({
		// 			...rest,
		// 		})
		// 		.where("userid", "=", userId)
		// 		.returningAll()
		// 		.executeTakeFirst();
		// }
		return await db
			.insertInto("users_anagrafica")
			.values({
				...rest,
				userid: userId,
			})
			.onConflict((oc) =>
				oc.column("userid").doUpdateSet({
					...rest,
				}),
			)
			.returningAll()
			.executeTakeFirst();
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Errore updateAnagrafica: ${(e as Error).message}`,
		});
	}
};

export const deleteUserHandler = async (id: UsersId) => {
	try {
		await db.deleteFrom("users").where("id", "=", id).execute();
		return { success: true };
	} catch {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: "errore cancellazione utente",
		});
	}
};

export const blockUserHandler = async (id: UsersId) => {
	return await db.transaction().execute(async (trx) => {
		return await trx
			.updateTable("users")
			.set((eb) => ({
				isBlocked: eb.not("isBlocked"),
			}))
			.where("id", "=", id)
			.where("isAdmin", "=", false)
			.returningAll()
			.execute();
	});
};

export const getUserHandler = async ({
	db,
	id,
}: {
	db: Querier;
	id: UsersId;
}) => {
	try {
		const user = await db
			.selectFrom("users")
			.leftJoin("users_anagrafica", "users_anagrafica.userid", "users.id")
			.where("id", "=", id)
			.selectAll()
			.executeTakeFirst();

		if (!user) {
			return null;
		}
		return user;
	} catch {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: "errore get utente",
		});
	}
};
export type UserWAnagrafica = Awaited<ReturnType<typeof getUserHandler>>;

export type NonNullableUser = {
	id: NonNullable<UsersId>;
	username: NonNullable<string>;
	nome: string | null;
};
export const getActiveUserWithoutChatHandler = async ({
	db,
}: {
	db: Querier;
}) => {
	const users = await db
		.selectFrom("users")
		.fullJoin("chats", "chats.user_ref", "users.id")
		.select(["users.id", "users.username", "users.nome"])
		.where("chats.chatid", "is", null)
		.where("users.isBlocked", "=", false)
		.where("users.isAdmin", "=", false)
		.execute();
	return users.filter((user): user is NonNullableUser => {
		return user.id !== null && user.username !== null;
	});
};

export type UserWChatInfo = Pick<
	Users,
	| "id"
	| "username"
	| "email"
	| "telefono"
	| "isAdmin"
	| "isBlocked"
	| "created_at"
	| "note"
> & { chatid: string | null; etichette: Etichette[] };

export const getUsersWithChatInfoHandler = async (): Promise<
	UserWChatInfo[]
> => {
	return await db
		.selectFrom("users")
		.select([
			"users.id",
			"users.username",
			"users.telefono",
			"users.email",
			"users.isAdmin",
			"users.isBlocked",
			"users.created_at",
			"users.note",
		])
		.leftJoin("chats", "chats.user_ref", "users.id")
		.select(["chats.chatid"])
		.select((eb) =>
			jsonArrayFrom(
				eb
					.selectFrom("etichette")
					.innerJoin(
						"user_etichette",
						"user_etichette.etichettaId",
						"etichette.id_etichetta",
					)
					.whereRef("user_etichette.userId", "=", "users.id")
					.select([
						"etichette.id_etichetta",
						"etichette.title",
						"etichette.color_hex",
					]),
			).as("etichette"),
		)
		.orderBy("users.id", "desc")
		.select(["users.id as id"])
		.execute();
};
