import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

import { deleteCookie, getCookie, setCookie } from "cookies-next";
import { useLogoutHandler } from "@/models/Auth/AuthModel";
import {
  AddUserRequest,
  AddUserResponse,
  DeleteUserRequest,
  DeleteUserResponse,
  GetAllUsersRequest,
  GetAllUsersResponse,
  SingleUserRequest,
  SingleUserResponse,
  UpdateUserRequest,
  UpdateUserResponse,
} from "./UserTypes";

const baseQuery = fetchBaseQuery({
  baseUrl: process.env.NEXT_PUBLIC_PORT,
  prepareHeaders: (headers) => {
    const user = getCookie("lookna_admin");
    const parsedUser = user ? JSON.parse(user as string) : null;

    const token = parsedUser?.data?.token;
    if (token) headers.set("Authorization", `Bearer ${token}`);
    return headers;
  },
});

const baseQueryWithReauth: typeof baseQuery = async (
  args,
  api,
  extraOptions
) => {
  let result = await baseQuery(args, api, extraOptions);

  if (
    result.error &&
    result.error.status === 403 &&
    (result.error.data as { message?: string })?.message ===
      "Invalid or expired token"
  ) {
    const user = getCookie("lookna_admin");
    const parsedUser = user ? JSON.parse(user as string) : null;
    const refreshToken = parsedUser?.data?.refreshToken;

    const refreshResult = await fetch(
      `${process.env.NEXT_PUBLIC_PORT}/api/refresh-token`,
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ refreshToken: refreshToken, deviceId: "Web" }),
      }
    );

    if (refreshResult.ok) {
      const data = await refreshResult.json();
      setCookie(
        "lookna_admin",
        JSON.stringify({
          ...parsedUser,
          data: { ...parsedUser.data, token: data.token },
        })
      );
      result = await baseQuery(args, api, extraOptions);
    } else {
      const errorData = await refreshResult.json();
      if (errorData?.message === "Invalid refresh token") {
        deleteCookie("lookna_admin");
        if (typeof window !== "undefined") {
          window.location.href = "/login";
        }
      }
    }
  }

  return result;
};

export const UserSlice = createApi({
  reducerPath: "UserSlice",
  baseQuery: baseQueryWithReauth,
  tagTypes: ["users"],
  endpoints: (build) => ({
    getAllUsers: build.query<GetAllUsersResponse, GetAllUsersRequest>({
      query: ({ page, limit, search }) => {
        const baseUrl = `/api/user/get-all-users?page=${page}&limit=${limit}?search=${search}`;
        let searchParams = "";
        if (search && typeof search === "object") {
          const searchEntries = Object.entries(search);
          if (searchEntries.length > 0) {
            searchParams =
              "&" +
              searchEntries
                .map(
                  ([key, value]) =>
                    `search[${key}]=${encodeURIComponent(value as string)}`
                )
                .join("&");
          }
        }
        return {
          url: baseUrl + searchParams,
          method: "GET",
        };
      },
      providesTags: ["users"],
    }),

    addUser: build.mutation<AddUserResponse, AddUserRequest>({
      query: (data) => ({
        url: "/api/user/add-user",
        method: "POST",
        body: data,
      }),
      invalidatesTags: ["users"],
    }),

    updateUser: build.mutation<UpdateUserResponse, UpdateUserRequest>({
      query: ({ userId, data }) => ({
        url: `/api/user/update-user/${userId}`,
        method: "PATCH",
        body: data,
      }),
      invalidatesTags: ["users"],
    }),

    singleUser: build.query<SingleUserResponse, SingleUserRequest>({
      query: ({ userId }) => ({
        url: `/api/user/get-single-user/${userId}`,
        method: "GET",
      }),
    }),

    deleteUser: build.mutation<DeleteUserResponse, DeleteUserRequest>({
      query: ({ userId }) => ({
        url: `/api/user/delete-user/${userId}`,
        method: "DELETE",
      }),
      invalidatesTags: ["users"],
    }),
  }),
});

export const {
  useGetAllUsersQuery,
  useAddUserMutation,
  useUpdateUserMutation,
  useSingleUserQuery,
  useDeleteUserMutation,
} = UserSlice;
