import { generateQueryString } from "@/utils/queryStringUtil";
import { apiSlice } from ".";
import URLS from "./constants";
import {
  BulkLeadUploadResultData,
  LeadAnalyticsResponse,
} from "@/types/lead";

export interface Lead {
  _id: string;
  id?: string;
  createdAt: string;
  updatedAt: string;

  fullName: string;
  email: string;
  phone: string;
  status: string;
  sourceId: string;
  companyId: string;
  assignedTo?: { id?: string };
  contact?: { companyName?: string };

  // Example populated fields
  source?: {
    _id: string;
    name: string;
  };
  company?: {
    _id: string;
    name: string;
  };
  success?: string;
  message?: string;
  data?: Lead;
}

interface GetLeadListResponse {
  data: {
    results: Lead[];
    page: number;
    limit: number;
    totalPages: number;
    totalResults: number;
    orphanLeadsCount?: number;
  };
  code: number;
  message: string;
  success: boolean;
  error?: object;
}

interface GetLeadByIdResponse {
  data: Lead;
  code: number;
  message: string;
  success: boolean;
  error?: object;
}

export interface CreateLeadBody {
  fullName: string;
  email: string;
  phone: string;
  status: string;
  sourceId: string;
  companyId: string;
  assignedTo?: string;
  cpContact?: string | null;
}

export interface SuggestedProperty {
  id: string;
  title: string;
  subcategory: {
    _id: string;
    name: string;
  };
  status: string;
  configuration: {
    _id: string;
    name: string;
  };
  locality: {
    _id: string;
    name: string;
  };
  city: {
    _id: string;
    name: string;
  };
  state?: {
    _id: string;
    name: string;
  };
  ownerName: string;
  ownerContact: string;
  price: number;
  monthlyRent?: number | null;
  availability: string;
  createdBy: { firstName: string };
}

interface GetSuggestedPropertiesResponse {
  code: number;
  message: string;
  data: SuggestedProperty[];
  success: boolean;
}

type UpdateLeadBody = Partial<CreateLeadBody>;

export interface BulkLeadPayload {
  assignedTo?: string;
  budget?: string;
  buyingPreference?: string;
  firstName: string;
  interestType: string;
  phone: string;
  project?: string;
  source: string;
  unit?: string;
}

/** Envelope from POST /lead/bulkUpload */
export interface BulkUploadApiResponse {
  code: number;
  message: string;
  data: BulkLeadUploadResultData;
  success: boolean;
  error?: object;
}

interface BulkUpdateLeadsResponse {
  code: number;
  message: string;
  success: boolean;
  data?: Lead[];
  error?: object;
}

interface BulkDeleteLeadsResponse {
  code: number;
  message: string;
  success: boolean;
  data?: Lead[];
  error?: object;
}

export interface TransferLeadBody {
  sourceMember: string;
  destMember: string;
  transferType: "temporary" | "permanent";
  leadTypes: "all" | "selected";
  transferStartDate?: string;
  transferEndDate?: string;
}

export interface TransferLeadResponse {
  code: number;
  message: string;
  success: boolean;
  data: {
    count: number;
    transferType: "temporary" | "permanent";
    destMember: string;
  };
}

export interface SuggestedProject {
  id: string;
  projectName: string;
  status: string;
  locality: {
    _id: string;
    name: string;
  };
  city: {
    _id: string;
    name: string;
  };
  state: {
    _id: string;
    name: string;
  };
  pricePerSqYard: number;
  createdBy: {
    _id: string;
    firstName: string;
    lastName: string;
  };
  companyId: string;
  mediaUrls: string[];
}

interface GetSuggestedProjectsResponse {
  code: number;
  message: string;
  data: SuggestedProject[];
  success: boolean;
}

export const leadApi = apiSlice.injectEndpoints({
  endpoints: (builder) => ({
    getLeads: builder.query<
      GetLeadListResponse,
      {
        page?: number;
        limit?: number;
        search?: string;
        sortBy?: string;
        populate?: string;
        status?: string;
        alias?: string;
        includeTimeStamps?: boolean;
        leadStage?: string;
        companyName?: string;
        company?: string;
        interestType?: string;
        source?: string;
        preferredCity?: any;
        preferredLocalities?: any;
        budget?: any;
        category?: any;
        propertyType?: any;
        orphanLeads?: boolean;
        configuration?: any;
        assignedTo?: any;
        project?: any;
        /** Kanban / list flag from backend */
        view?: string;
        /** For kanban per-stage pagination */
        stage?: string;
      }
    >({
      query: (params) => ({
        url: `${URLS.LEAD}?${generateQueryString(
          params as Record<string, unknown>,
        )}`,
        method: "GET",
      }),
      providesTags: ["Lead"],
    }),

    moveLead: builder.mutation<
      { code: number; message: string; success: boolean },
      { id: string; stage: string; beforeId?: string | null; afterId?: string | null }
    >({
      query: ({ id, stage, beforeId, afterId }) => {
        const body: {
          stage: string;
          beforeId?: string;
          afterId?: string;
        } = { stage };

        if (beforeId) {
          body.beforeId = beforeId;
        }

        if (afterId) {
          body.afterId = afterId;
        }

        return {
          url: `${URLS.LEAD}/${id}/move`,
          method: "PATCH",
          body,
        };
      },
      invalidatesTags: ["Lead"],
    }),

    getLeadById: builder.query<GetLeadByIdResponse, string>({
      query: (id) => ({
        url: `${URLS.LEAD}/${id}`,
        method: "GET",
        params: {
          populate:
            "preferredLocalities:name,id;preferredCity:name,id;preferredState:name,id;project:projectName,id;configuration:name,id;propertyType:name,id;contact:id,firstName,lastName,name,primaryPhone,phone,email,companyName;assignedTo:id,firstName,lastName;leadStage:stageName,id,color;source:name",
        },
      }),
      providesTags: ["Lead"],
    }),

    createLead: builder.mutation<Lead, CreateLeadBody>({
      query: (body) => ({
        url: `${URLS.LEAD}`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["Lead", "Task"],
    }),

    updateLead: builder.mutation<
      Lead,
      { id: string; body: UpdateLeadBody; checkCustomFieldValidation?: boolean }
    >({
      query: ({ id, body, checkCustomFieldValidation }) => {
        const params =
          checkCustomFieldValidation !== undefined
            ? { checkCustomFieldValidation }
            : undefined;

        return {
          url: `${URLS.LEAD}/${id}`,
          method: "PATCH",
          params,
          body,
        };
      },
      async onQueryStarted({ id, body }, { dispatch, queryFulfilled }) {
        const patchResult = dispatch(
          leadApi.util.updateQueryData("getLeadById", id, (draft: any) => {
            if (!draft?.data) return;

            if ((body as any)?.leadStage) {
              draft.data.leadStage = {
                ...(draft.data.leadStage ?? {}),
                id: (body as any).leadStage,
              };
            }

            if ((body as any)?.assignedTo) {
              draft.data.assignedTo = {
                ...(draft.data.assignedTo ?? {}),
                id: (body as any).assignedTo,
              };
            }
          }),
        );

        try {
          await queryFulfilled;
        } catch {
          patchResult.undo();
        }
      },
      invalidatesTags: (result, error, { id }) => [
        { type: "Lead", id },
        "Lead",
      ],
    }),

    deleteLead: builder.mutation<{ success: boolean }, string>({
      query: (id) => ({
        url: `${URLS.LEAD}/${id}`,
        method: "DELETE",
      }),
      invalidatesTags: (result, error, id) => [
        { type: "Lead", id },
        "Lead",
        "Task",
      ],
    }),

    checkRefLead: builder.query({
      query: (id) => ({
        url: `${URLS.LEAD}/${id}/referenceLead`,
        method: "GET",
      }),
    }),

    getLeadAnalytics: builder.query<LeadAnalyticsResponse, void>({
      query: () => ({
        url: `${URLS.LEAD}/analytics`,
        method: "GET",
      }),
    }),

    getSuggestedProperties: builder.query<
      GetSuggestedPropertiesResponse,
      {
        id?: string;
        model?: string;
        subcategory?: string;
        propertyType?: string;
        budgetMin?: string;
        budgetMax?: string;
        furnishingType?: string;
      }
    >({
      query: ({
        id,
        model,
        subcategory,
        propertyType,
        budgetMin,
        budgetMax,
        furnishingType,
      }) => {
        const params = new URLSearchParams();

        if (model) {
          params.append("model", model);
        }
        if (subcategory) {
          params.append("subcategory", subcategory);
        }
        if (propertyType) {
          params.append("propertyType", propertyType);
        }
        if (budgetMin) {
          params.append("budgetMin", budgetMin);
        }
        if (budgetMax) {
          params.append("budgetMax", budgetMax);
        }
        if (furnishingType) {
          params.append("furnishingType", furnishingType);
        }

        return {
          url: `${URLS.LEAD}/suggestedProperties/${id}?${params.toString()}`,
          method: "GET",
        };
      },
      providesTags: (result, error, { model }) =>
        model === "contact" ? ["Contact"] : ["Lead"],
    }),

    updateLeadShortList: builder.mutation<
      {
        code: number;
        message: string;
        data: SuggestedProperty;
        success: boolean;
      },
      {
        entityId?: string;
        type: "add" | "remove" | "delete";
        propertyId?: string; // optional
        projectId?: string; // optional
        model?: string;
      }
    >({
      query: ({ entityId, type, propertyId, projectId, model }) => {
        const params = new URLSearchParams({ type });

        if (propertyId) {
          params.append("propertyId", propertyId);
        } else if (projectId) {
          params.append("projectId", projectId);
        }

        if (model) {
          params.append("model", model);
        }

        return {
          url: `${URLS.LEAD}/shortList/${entityId}?${params.toString()}`,
          method: "PATCH",
        };
      },
      invalidatesTags: (result, error, { model }) =>
        model === "contact"
          ? ["Contact", "Activity"]
          : ["Lead", "Activity"],
    }),

    bulkUploadLeads: builder.mutation<
      BulkUploadApiResponse,
      BulkLeadPayload[]
    >({
      query: (body) => ({
        url: `${URLS.LEAD}/bulkUpload`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["Lead"],
    }),
    bulkUpdateLeads: builder.mutation<
      BulkUpdateLeadsResponse,
      { ids: string[]; updateData: Record<string, unknown> }
    >({
      query: (body) => ({
        url: `${URLS.LEAD}/bulkUpdate`,
        method: "PATCH",
        body,
      }),
      invalidatesTags: ["Lead"],
    }),
    bulkDeleteLeads: builder.mutation<
      BulkDeleteLeadsResponse,
      { ids: string[] }
    >({
      query: (body) => ({
        url: `${URLS.LEAD}/bulk-delete`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["Lead"],
    }),
    transferLead: builder.mutation<TransferLeadResponse, TransferLeadBody>({
      query: (body) => ({
        url: `${URLS.LEAD}/transferLead`,
        method: "POST",
        body,
      }),
      invalidatesTags: ["Lead"],
    }),

    getSuggestedProjects: builder.query<
      GetSuggestedProjectsResponse,
      { id?: string; model?: string }
    >({
      query: ({ id, model }) => ({
        url: `${URLS.LEAD}/suggestedProjects/${id}?model=${model}`,
        method: "GET",
      }),
      providesTags: (result, error, { model }) =>
        model === "contact" ? ["Contact"] : ["Lead"],
    }),
  }),
  overrideExisting: false,
});

export const {
  useGetLeadsQuery,
  useLazyGetLeadsQuery,
  useGetLeadByIdQuery,
  useCreateLeadMutation,
  useUpdateLeadMutation,
  useDeleteLeadMutation,
  useGetLeadAnalyticsQuery,
  useGetSuggestedPropertiesQuery,
  useUpdateLeadShortListMutation,
  useBulkUploadLeadsMutation,
  useBulkUpdateLeadsMutation,
  useBulkDeleteLeadsMutation,
  useTransferLeadMutation,
  useGetSuggestedProjectsQuery,
  useCheckRefLeadQuery,
  useMoveLeadMutation,
} = leadApi;
