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

  try {
    const [typesResult, permissions, valueTypesResult] = await Promise.all([
      optima.credentialType.fetchMany(accessToken),
      checkPermissions(accessToken, [
        "admin.credential-types.view",
        "admin.credential-types.create",
        "admin.credential-types.edit",
        "admin.credential-types.delete",
      ]),
      optima.credential.fetchValueTypes(accessToken).catch((err) => {
        console.error(
          "Failed to fetch value types:",
          err?.response?.data ?? err?.message ?? err,
        );
        return { data: [] };
      }),
    ]);

    const credentialTypes = typesResult?.data ?? [];
    const valueTypes: string[] = valueTypesResult?.data ?? [];

    return {
      credentialTypes,
      permissions,
      valueTypes,
    };
  } catch (err) {
    handleApiError(err);
  }
};

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

    const formData = await request.formData();
    const name = (formData.get("name") as string)?.trim();
    const permissionScope = (formData.get("permissionScope") as string)?.trim();
    const icon = (formData.get("icon") as string)?.trim() || undefined;
    const fieldsJson = (formData.get("fields") as string)?.trim();

    if (!name || !permissionScope) {
      return fail(400, { message: "Name and permission scope are required." });
    }

    let fields: Array<
      import("$lib/optima-api/modules/credentialTypes").CredentialTypeField
    > = [];
    if (fieldsJson) {
      try {
        fields = JSON.parse(fieldsJson);
      } catch {
        return fail(400, { message: "Invalid fields data." });
      }
    }

    try {
      await optima.credentialType.create(accessToken, {
        name,
        permissionScope,
        icon,
        fields,
      });
      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 credential type.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },

  updateCredentialType: 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 name = (formData.get("name") as string)?.trim();
    const permissionScope = (formData.get("permissionScope") as string)?.trim();
    const icon = (formData.get("icon") as string)?.trim() || undefined;
    const fieldsJson = (formData.get("fields") as string)?.trim();

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

    let fields:
      | Array<
          Omit<
            import("$lib/optima-api/modules/credentialTypes").CredentialTypeField,
            "id"
          >
        >
      | undefined;
    if (fieldsJson) {
      try {
        fields = JSON.parse(fieldsJson);
      } catch {
        return fail(400, { message: "Invalid fields data." });
      }
    }

    try {
      await optima.credentialType.update(accessToken, id, {
        name,
        permissionScope,
        icon,
        fields: fields as any,
      });
      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 credential type.");
      const status = (data?.status as number) ?? 500;
      return fail(status, { message });
    }
  },

  deleteCredentialType: 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: "Credential type ID is required." });
    }

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