// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
import { withIronSessionApiRoute } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { getEntities, getEntitiesWithRoles } from "@/utils/entities.be";
import { Entity, EntityWithRoles, WithEntities, WithLabeledEntities } from "@/interfaces/entity";
import { v4 } from "uuid";
import { mapBy } from "@/utils";
import { getEntitiesUsers, getUser, getUsers } from "@/utils/users.be";
import { User } from "@/interfaces/user";
import { findAllowedEntities } from "@/utils/permissions";
import { RolePermission } from "@/resources/entityPermissions";

export default withIronSessionApiRoute(handler, sessionOptions);

async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "GET") return await get(req, res);
}

const labelUserEntity = (u: User, entities: EntityWithRoles[]) => ({
  ...u, entities: (u.entities || []).map((e) => {
    const entity = entities.find((x) => x.id === e.id)
    if (!entity) return e

    const role = entity.roles.find((x) => x.id === e.role)
    return { id: e.id, label: entity.label, role: e.role, roleLabel: role?.label }
  })
})

async function get(req: NextApiRequest, res: NextApiResponse) {
  if (!req.session.user) return res.status(401).json({ ok: false });

  const user = await getUser(req.session.user.id)
  if (!user) return res.status(401).json({ ok: false });

  const { type } = req.query as { type: string }

  const entityIDs = mapBy(user.entities || [], 'id')
  const entities = await getEntitiesWithRoles(entityIDs)

  const isAdmin = ["admin", "developer"].includes(user.type)

  const filter = !type ? undefined : { type }
  const users = isAdmin
    ? await getUsers(filter)
    : await getEntitiesUsers(mapBy(entities, 'id') as string[], filter)

  const filteredUsers = users.map((u) => {
  	if (isAdmin) return labelUserEntity(u, entities)
  	if (!isAdmin && ["admin", "developer", "agent"].includes(user.type)) return undefined

   	const userEntities = mapBy(u.entities || [], 'id')
    const sameEntities = entities.filter(e => userEntities.includes(e.id))

    const permission = `view_${u.type}s` as RolePermission
    const allowedEntities = findAllowedEntities(user, sameEntities, permission)

    if (allowedEntities.length === 0) return undefined
    return labelUserEntity(u, allowedEntities)
  }).filter(x => !!x) as WithLabeledEntities<User>[]

  res.status(200).json(filteredUsers);
}
