import { TRPCError } from "@trpc/server";
import type { UsersId, UsersUpdate } from "~/schemas/public/Users";
import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
import type { Context } from "~/server/api/trpc";
import { db, type Querier } from "~/server/db";
import { checkCtxAdmin } from "~/server/utils/ctxChecker";

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 ({
	ctx,
	id,
}: {
	ctx: Context;
	id: UsersId;
}) => {
	checkCtxAdmin({ ctx });

	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 ({
	ctx,
	id,
}: {
	ctx: Context;
	id: UsersId;
}) => {
	checkCtxAdmin({ ctx });
	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 const getUsersWithChatInfoHandler = async ({ db }: { db: Querier }) => {
	return await db
		.selectFrom("users")
		.select([
			"users.id",
			"users.username",
			"users.email",
			"users.isAdmin",
			"users.isBlocked",
			"users.created_at",
		])
		.leftJoin("chats", "chats.user_ref", "users.id")
		.select(["chats.chatid"])
		.orderBy("users.id", "desc")
		.select(["users.id as id"])
		.execute();
};
