import { generateQueryString } from "@/utils/queryStringUtil";
import { apiSlice } from ".";
import URLS from "./constants";

// Request integration
export interface MyOperatorRequestBody {
  firstName: string;
  lastName: string;
  email: string;
  phone: { dialCode: number; number: number };
  companyName: string;
}

// Submit credentials
export interface MyOperatorCredentialsBody {
  apiToken: string;
  secretKey: string;
  xApiKey: string;
  companyId: string;
  isActive: boolean;
  virtualMobileNumber?: string;
  publicIvrId?: string;
}

// Sync user
export interface MyOperatorSyncUserBody {
  userId: string;
  extension?: number;
}

// Update user
export interface MyOperatorUpdateUserBody {
  name?: string;
  email?: string;
  contact_number?: string;
  country_code?: string;
  extension?: number;
  panel_access?: number;
  receive_calls?: number;
  contact_type?: "mobile" | "sip" | "landline";
}

// List users query
export interface MyOperatorUsersQuery {
  keyword?: string;
  page?: number;
  pageSize?: number;
  all?: boolean;
}

// Call logs query
export interface MyOperatorCallLogsQuery {
  from?: number;
  to?: number;
  logFrom?: number;
  pageSize?: number;
  searchKey?: string;
  filters?: string;
}

export interface MyOperatorUser {
  uuid: string;
  name: string;
  email: string;
  extension: number;
  /** Contact number for matching with company users (e.g. from MyOperator list API) */
  contact_number?: string;
  country_code?: string;
}

export interface MyOperatorCallLog {
  id: string;
  caller: string;
  callee: string;
  duration: number;
  timestamp: string;
}

export interface MyOperatorCallFilter {
  id: number;
  name: string;
}

export interface MyOperatorInitiateCallBody {
  userId: string;
  leadId: string;
  contactId: string;
}

export const myoperatorApi = apiSlice.injectEndpoints({
  endpoints: (builder) => ({
    postRequest: builder.mutation<
      { success: boolean; message?: string; data?: unknown },
      MyOperatorRequestBody
    >({
      query: (body) => ({
        url: `${URLS.MYOPERATOR}/request`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["MyOperator"],
    }),

    postCredentials: builder.mutation<
      { success: boolean; message?: string; data?: unknown },
      MyOperatorCredentialsBody
    >({
      query: (body) => ({
        url: `${URLS.MYOPERATOR}/credentials`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["MyOperator"],
    }),

    postCredentialsTest: builder.mutation<
      { success: boolean; message?: string; data?: unknown },
      void
    >({
      query: () => ({
        url: `${URLS.MYOPERATOR}/credentials/test`,
        method: "POST",
        body: {},
      }),
    }),

    syncUser: builder.mutation<
      { success: boolean; message?: string; data?: { uuid?: string; extension?: number } },
      MyOperatorSyncUserBody
    >({
      query: (body) => ({
        url: `${URLS.MYOPERATOR}/users/sync`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["MyOperator", "MyOperatorUsers"],
    }),

    initiateCall: builder.mutation<
      { success: boolean; message?: string; data?: unknown },
      MyOperatorInitiateCallBody
    >({
      query: (body) => ({
        url: `${URLS.MYOPERATOR}/call/initiate`,
        method: "POST",
        body,
      }),
    }),

    getMyOperatorUsers: builder.query<
      {
        success: boolean;
        data?: { users: MyOperatorUser[]; count: number };
        message?: string;
      },
      MyOperatorUsersQuery | void
    >({
      query: (params) => ({
        url: params
          ? `${URLS.MYOPERATOR}/users?${generateQueryString(params as Record<string, unknown>)}`
          : `${URLS.MYOPERATOR}/users`,
        method: "GET",
      }),
      providesTags: ["MyOperatorUsers"],
    }),

    updateMyOperatorUser: builder.mutation<
      { success: boolean; message?: string },
      { userId: string; body: MyOperatorUpdateUserBody }
    >({
      query: ({ userId, body }) => ({
        url: `${URLS.MYOPERATOR}/users/${userId}`,
        method: "PUT",
        body,
      }),
      invalidatesTags: ["MyOperator", "MyOperatorUsers"],
    }),

    deleteMyOperatorUser: builder.mutation<
      { success: boolean; message?: string },
      string
    >({
      query: (userId) => ({
        url: `${URLS.MYOPERATOR}/users/${userId}`,
        method: "DELETE",
      }),
      invalidatesTags: ["MyOperator", "MyOperatorUsers", "User"],
    }),

    getCallLogs: builder.query<
      {
        success: boolean;
        data?: { logs: MyOperatorCallLog[]; count: number };
        message?: string;
      },
      MyOperatorCallLogsQuery | void
    >({
      query: (params) => ({
        url: params
          ? `${URLS.MYOPERATOR}/call/logs?${generateQueryString(params as Record<string, unknown>)}`
          : `${URLS.MYOPERATOR}/call/logs`,
        method: "GET",
      }),
      providesTags: ["MyOperatorCallLogs"],
    }),

    getCallFilters: builder.query<
      { success: boolean; data?: { filters: MyOperatorCallFilter[] }; message?: string },
      void
    >({
      query: () => ({
        url: `${URLS.MYOPERATOR}/call/filters`,
        method: "GET",
      }),
    }),

    getCallRecording: builder.query<
      { success: boolean; data?: { downloadUrl: string; expiresAt: string }; message?: string },
      string
    >({
      query: (filename) => ({
        url: `${URLS.MYOPERATOR}/call/recording/${encodeURIComponent(filename)}`,
        method: "GET",
      }),
    }),

    getCallStatus: builder.query<
      { success: boolean; data?: unknown; message?: string },
      { userId: string }
    >({
      query: ({ userId }) => ({
        url: `${URLS.MYOPERATOR}/call/status?userId=${encodeURIComponent(
          userId,
        )}`,
        method: "GET",
      }),
    }),
  }),
});

export const {
  usePostRequestMutation,
  usePostCredentialsMutation,
  usePostCredentialsTestMutation,
  useSyncUserMutation,
  useInitiateCallMutation,
  useGetMyOperatorUsersQuery,
  useUpdateMyOperatorUserMutation,
  useDeleteMyOperatorUserMutation,
  useGetCallLogsQuery,
  useGetCallFiltersQuery,
  useGetCallRecordingQuery,
  useGetCallStatusQuery,
  useLazyGetCallStatusQuery,
} = myoperatorApi;
