"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";

import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";

const invitationTokenSchema = z.string().min(1).max(500);

export const getInvitations = async ({
  page = 1,
  query = "",
  sort = "",
  filters = {},
  pageSize = 10,
}) => {
  const headers = await getAuthHeaders({ contentType: false });

  if (isNaN(Number(page)) || page < 1) redirect("/invitations");

  const url = new URL(`${apiBaseUrl}/tenants/invitations`);

  if (page) url.searchParams.append("page[number]", page.toString());
  if (pageSize) url.searchParams.append("page[size]", pageSize.toString());
  if (query) url.searchParams.append("filter[search]", query);
  if (sort) url.searchParams.append("sort", sort);

  // Handle multiple filters
  Object.entries(filters).forEach(([key, value]) => {
    if (key !== "filter[search]") {
      url.searchParams.append(key, String(value));
    }
  });

  try {
    const response = await fetch(url.toString(), {
      headers,
    });

    return handleApiResponse(response);
  } catch (error) {
    console.error("Error fetching invitations:", error);
    return undefined;
  }
};

export const sendInvite = async (formData: FormData) => {
  const headers = await getAuthHeaders({ contentType: true });

  const email = formData.get("email");
  const role = formData.get("role");
  const url = new URL(`${apiBaseUrl}/tenants/invitations`);

  const body = JSON.stringify({
    data: {
      type: "invitations",
      attributes: {
        email,
      },
      relationships: {
        roles: {
          data: role
            ? [
                {
                  id: role,
                  type: "roles",
                },
              ]
            : [],
        },
      },
    },
  });

  try {
    const response = await fetch(url.toString(), {
      method: "POST",
      headers,
      body,
    });

    return handleApiResponse(response);
  } catch (error) {
    handleApiError(error);
  }
};

export const updateInvite = async (formData: FormData) => {
  const headers = await getAuthHeaders({ contentType: true });

  const invitationId = formData.get("invitationId");
  const invitationEmail = formData.get("invitationEmail");
  const roleId = formData.get("role");
  const expiresAt =
    formData.get("expires_at") ||
    new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();

  const url = new URL(`${apiBaseUrl}/tenants/invitations/${invitationId}`);

  const body: any = {
    data: {
      type: "invitations",
      id: invitationId,
      attributes: {},
      relationships: {},
    },
  };

  // Only add attributes that exist in the formData
  if (invitationEmail) {
    body.data.attributes.email = invitationEmail;
  }
  if (expiresAt) {
    body.data.attributes.expires_at = expiresAt;
  }
  if (roleId) {
    body.data.relationships.roles = {
      data: [
        {
          id: roleId,
          type: "roles",
        },
      ],
    };
  }

  try {
    const response = await fetch(url.toString(), {
      method: "PATCH",
      headers,
      body: JSON.stringify(body),
    });

    if (!response.ok) {
      const error = await response.json();
      return { error };
    }

    return handleApiResponse(response, "/invitations");
  } catch (error) {
    handleApiError(error);
  }
};

export const getInvitationInfoById = async (invitationId: string) => {
  const headers = await getAuthHeaders({ contentType: false });
  const url = new URL(`${apiBaseUrl}/tenants/invitations/${invitationId}`);

  try {
    const response = await fetch(url.toString(), {
      method: "GET",
      headers,
    });

    return handleApiResponse(response);
  } catch (error) {
    handleApiError(error);
  }
};

export const revokeInvite = async (formData: FormData) => {
  const headers = await getAuthHeaders({ contentType: false });
  const invitationId = formData.get("invitationId");

  if (!invitationId) {
    return { error: "Invitation ID is required" };
  }

  const url = new URL(`${apiBaseUrl}/tenants/invitations/${invitationId}`);

  try {
    const response = await fetch(url.toString(), {
      method: "DELETE",
      headers,
    });

    if (!response.ok) {
      try {
        const errorData = await response.json();
        throw new Error(
          errorData?.message || "Failed to revoke the invitation",
        );
      } catch {
        throw new Error("Failed to revoke the invitation");
      }
    }

    let data = null;
    if (response.status !== 204) {
      data = await response.json();
    }

    revalidatePath("/invitations");
    return data || { success: true };
  } catch (error) {
    handleApiError(error);
  }
};

export const acceptInvitation = async (token: string) => {
  const parsed = invitationTokenSchema.safeParse(token);
  if (!parsed.success) {
    return { error: "Invalid invitation token" };
  }

  const headers = await getAuthHeaders({ contentType: true });

  const url = new URL(`${apiBaseUrl}/invitations/accept`);

  const body = JSON.stringify({
    data: {
      type: "invitations",
      attributes: {
        invitation_token: parsed.data,
      },
    },
  });

  try {
    const response = await fetch(url.toString(), {
      method: "POST",
      headers,
      body,
    });

    return handleApiResponse(response);
  } catch (error) {
    return handleApiError(error);
  }
};
