import { ContentfulStatusCode } from "hono/utils/http-status";
import { z } from "zod";
import { apiResponse } from "../../modules/api-utils/apiResponse";
import { createRoute } from "../../modules/api-utils/createRoute";
import { authMiddleware } from "../middleware/authorization";
import { users } from "../../managers/users";
import GenericError from "../../Errors/GenericError";

const updateSchema = z
  .object({
    name: z.string().optional(),
    firstName: z.string().nullable().optional(),
    lastName: z.string().nullable().optional(),
    image: z.string().optional(),
    roles: z.array(z.string()).optional(),
    permissions: z.array(z.string()).optional(),
  })
  .strict();

/* PATCH /v1/user/users/:identifier */
export default createRoute(
  "patch",
  ["/users/:identifier"],

  async (c) => {
    const identifier = c.req.param("identifier");
    const requestingUser = c.get("user");

    const user = await users.fetchUser({ id: identifier });
    if (!user)
      throw new GenericError({
        name: "UserNotFound",
        message: `User with identifier '${identifier}' was not found.`,
        status: 404,
      });

    const body = updateSchema.parse(await c.req.json());

    if (body.roles && !(await requestingUser.hasPermission("user.roles.other")))
      throw new GenericError({
        name: "InsufficientPermission",
        message: "You do not have permission to modify roles on another user.",
        status: 403,
      });

    if (
      body.permissions &&
      !(await requestingUser.hasPermission("user.permissions.other"))
    )
      throw new GenericError({
        name: "InsufficientPermission",
        message:
          "You do not have permission to modify permissions on another user.",
        status: 403,
      });

    const { roles: roleIds, permissions, ...profileData } = body;

    if (Object.keys(profileData).length > 0) await user.update(profileData);
    if (roleIds) await user.setRoles(roleIds);
    if (permissions) await user.setPermissions(permissions);

    const response = apiResponse.successful(
      "User Updated Successfully!",
      user.toJson()
    );
    return c.json(response, response.status as ContentfulStatusCode);
  },
  authMiddleware({ permissions: ["user.write.other"] })
);
