import { optima } from "$lib";
import { handleApiError } from "$lib/optima-api/errorHandler";
import { checkPermissions } from "$lib/permissions";
import { fail } from "@sveltejs/kit";
import type { Actions, PageServerLoad } from "./$types";
import { AxiosError } from "axios";

export const load: PageServerLoad = async ({ locals }) => {
  const accessToken = locals.session?.accessToken;
  if (!accessToken) {
    return { users: [], roles: [], permissions: {} };
  }

  try {
    const [usersResult, rolesResult, permissions, permNodesResult] =
      await Promise.all([
        optima.users.fetchAll(accessToken),
        optima.role.fetchMany(accessToken),
        checkPermissions(accessToken, [
          "admin.users.view",
          "admin.users.edit",
          "admin.users.delete",
          "user.roles.other",
          "user.permissions.other",
        ]),
        optima.permission
          .fetchCategorized(accessToken)
          .catch(() => ({ data: {} })),
      ]);

    const allUsers = usersResult?.data ?? [];
    const allRoles = rolesResult?.data ?? [];

    // Fetch roles for each user in parallel
    const usersWithRoles = await Promise.all(
      allUsers.map(async (user) => {
        try {
          const rolesResult = await optima.users.fetchRoles(
            accessToken,
            user.id
          );
          return { ...user, roleDetails: rolesResult?.data ?? [] };
        } catch {
          return { ...user, roleDetails: [] };
        }
      })
    );

    return {
      users: usersWithRoles,
      roles: allRoles,
      permissions,
      permissionNodes: permNodesResult?.data ?? {},
    };
  } catch (err) {
    handleApiError(err);
  }
};

export const actions: Actions = {
  updateUser: async ({ locals, request }) => {
    const accessToken = locals.session?.accessToken;
    if (!accessToken) {
      return fail(401, { message: "Not authenticated." });
    }

    const formData = await request.formData();
    const id = (formData.get("id") as string)?.trim();
    const firstName = (formData.get("firstName") as string)?.trim();
    const lastName = (formData.get("lastName") as string)?.trim();
    const image = (formData.get("image") as string)?.trim() || undefined;
    const rolesJson = (formData.get("roles") as string)?.trim();
    const permissionsJson = (formData.get("permissions") as string)?.trim();

    if (!id) {
      return fail(400, { message: "User ID is required." });
    }

    const updates: {
      firstName?: string | null;
      lastName?: string | null;
      image?: string;
      roles?: string[];
      permissions?: string[];
    } = { image };

    if (formData.has("firstName")) {
      updates.firstName = firstName || null;
    }
    if (formData.has("lastName")) {
      updates.lastName = lastName || null;
    }

    if (rolesJson) {
      try {
        updates.roles = JSON.parse(rolesJson);
      } catch {
        return fail(400, { message: "Invalid roles data." });
      }
    }

    if (permissionsJson) {
      try {
        updates.permissions = JSON.parse(permissionsJson);
      } catch {
        return fail(400, { message: "Invalid permissions data." });
      }
    }

    try {
      await optima.users.update(accessToken, id, updates);
      return {};
    } catch (err: unknown) {
      const data = (err as AxiosError)?.response?.data as
        | Record<string, unknown>
        | undefined;
      const message =
        (data?.message as string) ??
        (err instanceof Error ? err.message : "Failed to update user.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },

  deleteUser: async ({ locals, request }) => {
    const accessToken = locals.session?.accessToken;
    if (!accessToken) {
      return fail(401, { message: "Not authenticated." });
    }

    const formData = await request.formData();
    const id = (formData.get("id") as string)?.trim();

    if (!id) {
      return fail(400, { message: "User ID is required." });
    }

    try {
      await optima.users.delete(accessToken, id);
      return {};
    } catch (err: unknown) {
      const data = (err as AxiosError)?.response?.data as
        | Record<string, unknown>
        | undefined;
      const message =
        (data?.message as string) ??
        (err instanceof Error ? err.message : "Failed to delete user.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },
};
