import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { RootState } from "../../store";
import {
  getRequest,
  patchRequest,
  postRequest,
} from "../../../config/axois/apiRequest";
import { showError, showSuccess } from "../../../components/alerts/alerts";
import { OK } from "../../../config/axois/apiStatusCode";
import { vendorsApi } from "../../../config/apiUrls/apiUrl";
import { errorHandler, isEmpty } from "../../../helper/helper";

export interface Vendor {
  id: string | number;
  name: string;
  type: string;
  phone_no: string;
  email?: string | null;
  note?: string | null;
}

interface VendorsListing extends Vendor {
  created_by: string;
  deleted_at?: string;
}

interface VendorsState {
  vendors: VendorsListing[];
  vendorsList: VendorsListing[];
  details: Vendor | null;
  loading: boolean;
  vendorListLoading: boolean;
  detailsLoading: boolean;
  error: string | null;
}

interface QueryParam {
  currentOffset: number;
  limit: number;
  search?: string;
  projectId?: number;
  projectIdList?: number;
  ordering?: string;
  isModal?: boolean;
  isDeleted?: boolean;
}

const initialState: VendorsState = {
  vendors: [],
  vendorsList: [],
  details: null,
  loading: false,
  vendorListLoading: false,
  detailsLoading: false,
  error: null,
};

export const fetchVendors: any = createAsyncThunk(
  "vendors/fetchVendors",
  async ({
    currentOffset,
    limit,
    search,
    projectId,
    ordering,
    projectIdList,
    isModal,
    isDeleted,
  }: QueryParam) => {
    try {
      let url = `${vendorsApi.getVendors}?limit=${limit}&offset=${currentOffset}`;

      if (!isEmpty(search)) {
        url += `&search=${search}`;
      }

      if (!isEmpty(projectId)) {
        url += `&vendors_without_project_id=${projectId}`;
      }

      if (!isEmpty(projectIdList)) {
        url += `&project_id=${projectIdList}`;
      }

      if (!isEmpty(ordering)) {
        url += `&ordering=${ordering}`;
      }

      if (isDeleted) {
        url += `&with_trashed=true`;
      }

      const response = await getRequest(url, true);

      return { ...response, isModal: isModal };
    } catch (error: any) {
      return error;
    }
  }
);

export const clearVendors: any = createAsyncThunk(
  "vendors/clearVendors",
  async (value: boolean) => {
    return value;
  }
);

export const createVendor = createAsyncThunk(
  "vendors/createVendor",
  async (newVendor: Omit<Vendor, "id">) => {
    // Omitting "id" from newVendor
    try {
      const response = await postRequest(
        vendorsApi.createVendor,
        newVendor,
        true
      );

      return response;
    } catch (error: any) {
      if (error?.response?.data?.errors) {
        errorHandler(error?.response?.data?.errors);
        return;
      } else {
        showError("Something Went Wrong");
      }

      return error;
    }
  }
);

export const updateVendor = createAsyncThunk(
  "vendors/updateVendor",
  async (updatedVendor: Vendor) => {
    try {
      const response = await patchRequest(
        vendorsApi.updateVendor + updatedVendor.id,
        updatedVendor,
        true
      );

      return response;
    } catch (error: any) {
      if (error?.response?.data?.errors) {
        errorHandler(error?.response?.data?.errors);
        return;
      } else {
        showError("Something Went Wrong");
      }

      return error;
    }
  }
);

export const getVendorById = createAsyncThunk(
  "vendors/getVendorById",
  async (vendorId: any) => {
    try {
      const response = await getRequest(
        `${vendorsApi.getVendors}/${vendorId}`,
        true
      );

      return response;
    } catch (error: any) {
      return error;
    }
  }
);

const vendorsSlice = createSlice({
  name: "projects",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchVendors.pending, (state, action) => {
        if (action?.meta?.arg?.isModal) {
          state.vendorListLoading = true;
        } else {
          state.loading = true;
        }

        state.error = null;
      })
      .addCase(fetchVendors.fulfilled, (state, action) => {
        // only for add vendor modal in project details
        if (action.payload?.isModal) {
          state.vendorListLoading = false;
          state.vendorsList = [
            ...state.vendorsList,
            ...(action.payload?.data?.data ?? []),
          ];
        } else {
          state.loading = false;
          state.vendors = action.payload?.data?.data ?? [];
        }
      })
      .addCase(clearVendors.fulfilled, (state, action) => {
        state.vendorsList = [];
      })
      .addCase(fetchVendors.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || "Failed to fetch vendors";
      })
      .addCase(createVendor.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Vendor Added Successfully");
        }
      })
      .addCase(updateVendor.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Vendor Updated Successfully");
        }
      })
      .addCase(getVendorById.pending, (state) => {
        state.detailsLoading = true;
        state.error = null;
      })
      .addCase(getVendorById.fulfilled, (state, action) => {
        state.detailsLoading = false;
        state.details = action?.payload?.data?.data ?? null;
      })
      .addCase(getVendorById.rejected, (state, action) => {
        state.detailsLoading = false;
        state.error = action.error.message || "Failed to fetch vendor";
      });
  },
});

// Selectors
export const vendorsSelectors = {
  vendors: (state: RootState) => state.vendors.vendors,
  vendorsList: (state: RootState) => state.vendors.vendorsList,
  details: (state: RootState) => state.vendors.details,
  loading: (state: RootState) => state.vendors.loading,
  vendorListLoading: (state: RootState) => state.vendors.vendorListLoading,
  detailsLoading: (state: RootState) => state.vendors.detailsLoading,
  error: (state: RootState) => state.vendors.error,
};

const vendorReducer = vendorsSlice.reducer;

export default vendorReducer;
