import {Entity, EntityWithRoles, Role} from "@/interfaces/entity";
import client from "@/lib/mongodb";
import { ADMIN_PERMISSIONS, DEFAULT_PERMISSIONS, RolePermission } from "@/resources/entityPermissions";
import { v4 } from "uuid";
import {getRolesByEntities, getRolesByEntity} from "./roles.be";

const db = client.db(process.env.MONGODB_DB);

export const getEntityWithRoles = async (id: string): Promise<EntityWithRoles | undefined> => {
	const entity = await getEntity(id);
	if (!entity) return undefined;

	const roles = await getRolesByEntity(id);
	return {...entity, roles};
};

export const getEntity = async (id: string) => {
	return (await db.collection("entities").findOne<Entity>({id})) ?? undefined;
};

export const getEntitiesWithRoles = async (ids?: string[]): Promise<EntityWithRoles[]> => {
	const entities = await db
		.collection("entities")
		.find<Entity>(ids ? {id: {$in: ids}} : {})
		.toArray();

	const roles = await getRolesByEntities(entities.map((x) => x.id));

	return entities.map((x) => ({...x, roles: roles.filter((y) => y.entityID === x.id) || []}));
};

export const getEntities = async (ids?: string[]) => {
	return await db
		.collection("entities")
		.find<Entity>(ids ? {id: {$in: ids}} : {})
		.toArray();
};

export const createEntity = async (entity: Entity) => {
	await db.collection("entities").insertOne(entity)

	const defaultRole = {
		id: v4(),
		label: "Default",
		permissions: DEFAULT_PERMISSIONS,
		isDefault: true,
		entityID: entity.id
	}

	const adminRole = {
		id: v4(),
		label: "Admin",
		permissions: ADMIN_PERMISSIONS,
		entityID: entity.id
	}

	await db.collection("roles").insertOne(defaultRole)
	await db.collection("roles").insertOne(adminRole)

	return {default: defaultRole, admin: adminRole}
}

export const addUserToEntity = async (user: string, entity: string, role: string) =>
	await db.collection("users").updateOne(
		{id: user},
		{
			// @ts-expect-error
			$push: {
				entities: {id: entity, role},
			},
		},
	);

export const addUsersToEntity = async (users: string[], entity: string, role: string) =>
	await db.collection("users").updateMany(
		{id: {$in: users}},
		{
			// @ts-expect-error
			$push: {
				entities: {id: entity, role},
			},
		},
	);

export const deleteEntity = async (entity: Entity) => {
	await db.collection("entities").deleteOne({id: entity.id})
	await db.collection("roles").deleteMany({entityID: entity.id})

	await db.collection("users").updateMany(
		{"entities.id": entity.id},
		{
			// @ts-expect-error
			$pull: {
				entities: {id: entity.id},
			},
		},
	);
}
