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 { roles: [], permissions: {}, permissionNodes: {} };
  }

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

    const roles = rolesResult?.data ?? [];

    // Fetch users for each role in parallel
    const rolesWithUsers = await Promise.all(
      roles.map(async (role: Record<string, unknown>) => {
        try {
          const usersResult = await optima.role.fetchUsers(
            accessToken,
            role.id as string,
          );
          return { ...role, users: usersResult?.data ?? [] };
        } catch {
          return { ...role, users: [] };
        }
      }),
    );

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

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

    const formData = await request.formData();
    const title = (formData.get("title") as string)?.trim();
    const moniker = (formData.get("moniker") as string)?.trim();
    const permissions = formData.getAll("permissions") as string[];

    if (!title || !moniker) {
      return fail(400, { message: "Title and moniker are required." });
    }

    try {
      await optima.role.create(accessToken, { title, moniker, permissions });
      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 create role.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },

  updateRole: 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 title = (formData.get("title") as string)?.trim();
    const moniker = (formData.get("moniker") as string)?.trim();
    const permissions = formData.getAll("permissions") as string[];

    if (!id || !title || !moniker) {
      return fail(400, { message: "Required fields are missing." });
    }

    try {
      await optima.role.update(accessToken, id, {
        title,
        moniker,
        permissions,
      });
      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 role.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },

  deleteRole: 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: "Role ID is required." });
    }

    try {
      await optima.role.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 role.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },
};
