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

export interface Project {
  id: string | number;
  name: string;
  client: number;
  address?: string | null;
  note: string | null;
  budget: number;
  description: string | null;
}

interface ProjectListing {
  id: number;
  name: string;
  client_name: string;
  total_vendors: string;
  total_working_duration?: string | null;
  deleted_at?: string | null;
  total_amount?: string | null;
}

interface Vendor {
  id: number;
  name: string;
  type: string;
  phone_no: string;
}

interface ProjectDetails {
  id: number;
  name: string;
  vendors: Vendor[];
  client: number;
  client_name: string;
  client_phone_no: string;
  client_address: string;
  address: string;
  note: string;
  budget: number;
  description: string;
  deleted_at?: string | null;
  minutes_of_meeting?: string | null;
}

interface ProjectsState {
  projects: ProjectListing[];
  details: ProjectDetails | null;
  loading: boolean;
  detailsLoading: boolean;
  error: string | null;
}

interface QueryParam {
  currentOffset: number;
  limit: number;
  employeeId?: number;
  search?: string;
  ordering?: string;
  clientId?: number;
  vendorId?: number;
  consultantId?: number;
  contractorId?: number;
  isDeleted?: boolean;
}

const initialState: ProjectsState = {
  projects: [],
  details: null,
  loading: false,
  detailsLoading: false,
  error: null,
};

interface ProjectVendors {
  id: number;
  vendor_id: number[];
  modalType: string;
}
interface AssignEmployees {
  id: number;
  employee_ids: number[];
}

export const fetchProjects: any = createAsyncThunk(
  "projects/fetchProjects",
  async ({
    currentOffset,
    limit,
    employeeId,
    search,
    ordering,
    clientId,
    vendorId,
    contractorId,
    consultantId,
    isDeleted,
  }: QueryParam) => {
    try {
      let url = `${projectsApi.getProjects}?limit=${limit}&offset=${currentOffset}`;

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

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

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

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

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

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

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

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

      const response = await getRequest(url, true);

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

export const createProject = createAsyncThunk(
  "projects/createProject",
  async (newProject: Omit<Project, "id">) => {
    // Omitting "id" from newProject
    try {
      const response = await postRequest(
        projectsApi.createProject,
        newProject,
        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 updateProject = createAsyncThunk(
  "projects/updateProject",
  async (updatedProject: Project) => {
    try {
      const response = await patchRequest(
        projectsApi.updateProject + updatedProject.id,
        updatedProject,
        true
      );

      return response;
    } catch (error: any) {
      if (error?.response?.data?.errors) {
        errorHandler(error?.response?.data?.errors);

        return;
      } else {
        showError("Something Went Wrong 111");
      }

      return error;
    }
  }
);

export const updateMinutesOfMeetings = createAsyncThunk(
  "projects/updateMinutesOfMeetings",
  async (body: { id: string; minutes_of_meeting: string }) => {
    try {
      const response = await patchRequest(
        projectsApi.updateMinutesOfMeetings.replace(":id", body.id),
        { minutes_of_meeting: body.minutes_of_meeting },
        true
      );

      return response;
    } catch (error: any) {
      if (error?.response?.data?.errors) {
        errorHandler(error?.response?.data?.errors);

        return;
      } else {
        showError("Something Went Wrong 111");
      }

      return error;
    }
  }
);

export const getProjectById = createAsyncThunk(
  "projects/getProjectById",
  async (projectId: any) => {
    try {
      const response = await getRequest(
        `${projectsApi.getProjectsDetails}/${projectId}`,
        true
      );

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

export const assignVendor = createAsyncThunk(
  "projects/assignVendor",
  async (assignVendor: ProjectVendors) => {
    try {
      let url = "";
      let body = {};

      if (assignVendor.modalType === "vendor") {
        url = `${projectsApi.getProjects}/${assignVendor.id}/assign-vendor`;
        body = { vendor_id: assignVendor.vendor_id };
      }

      if (assignVendor.modalType === "contractor") {
        url = `${projectsApi.getProjects}/${assignVendor.id}/assign-contractor`;
        body = { contractor_id: assignVendor.vendor_id };
      }

      if (assignVendor.modalType === "consultant") {
        url = `${projectsApi.getProjects}/${assignVendor.id}/assign-consultant`;
        body = { consultant_id: assignVendor.vendor_id };
      }

      const response = await postRequest(url, body, true);

      return response;
    } catch (error: any) {
      showError(error.message);
      return error;
    }
  }
);

export const unAssignVendor = createAsyncThunk(
  "projects/unAssignVendor",
  async (unAssignVendor: ProjectVendors) => {
    try {
      let url = "";
      let body = {};

      if (unAssignVendor.modalType === "vendor") {
        url = `${projectsApi.getProjects}/${unAssignVendor.id}/unassign-vendor`;
        body = { vendor_id: unAssignVendor.vendor_id };
      }

      if (unAssignVendor.modalType === "contractor") {
        url = `${projectsApi.getProjects}/${unAssignVendor.id}/unassign-contractor`;
        body = { contractor_id: unAssignVendor.vendor_id };
      }

      if (unAssignVendor.modalType === "consultant") {
        url = `${projectsApi.getProjects}/${unAssignVendor.id}/unassign-consultant`;
        body = { consultant_id: unAssignVendor.vendor_id };
      }

      const response = await postRequest(url, body, true);

      return response;
    } catch (error: any) {
      showError(error.message);
      return error;
    }
  }
);

export const assignEmployees = createAsyncThunk(
  "employees/assignEmployees",
  async (assignEmployee: AssignEmployees) => {
    try {
      const response = await postRequest(
        `${projectsApi.getProjects}/${assignEmployee.id}/assign-employees`,
        { employee_ids: assignEmployee.employee_ids },
        true
      );

      return response;
    } catch (error: any) {
      showError(error.message);

      return error;
    }
  }
);

export const unAssignEmployees = createAsyncThunk(
  "employees/unAssignEmployees",
  async (assignEmployee: AssignEmployees) => {
    try {
      const response = await postRequest(
        `${projectsApi.getProjects}/${assignEmployee.id}/unassign-employees`,
        { employee_ids: assignEmployee.employee_ids },
        true
      );

      return response;
    } catch (error: any) {
      showError(error.message);

      return error;
    }
  }
);

const projectsSlice = createSlice({
  name: "projects",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchProjects.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchProjects.fulfilled, (state, action) => {
        state.loading = false;
        state.projects = action?.payload?.data?.data ?? {};
      })
      .addCase(fetchProjects.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || "Failed to fetch projects";
      })
      .addCase(createProject.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Project Added Successfully");
        }
      })
      .addCase(updateProject.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Project Updated Successfully");
        }
      })
      .addCase(updateMinutesOfMeetings.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Minutes of Meeting Updated Successfully");
        }
      })
      .addCase(getProjectById.pending, (state) => {
        state.detailsLoading = true;
        state.error = null;
      })
      .addCase(getProjectById.fulfilled, (state, action) => {
        state.detailsLoading = false;
        state.details = action?.payload?.data?.data ?? null;
      })
      .addCase(getProjectById.rejected, (state, action) => {
        state.detailsLoading = false;
        state.error = action.error.message || "Failed to fetch project";
      })
      .addCase(assignVendor.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Vendors Assigned Successfully");
        }
      })
      .addCase(unAssignVendor.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Vendor Unassigned Successfully");
        }
      })
      .addCase(assignEmployees.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Employees Assigned Successfully");
        }
      })
      .addCase(unAssignEmployees.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Employee Unassigned Successfully");
        }
      });
  },
});

// Selectors
export const projectsSelectors = {
  projects: (state: RootState) => state.projects.projects,
  details: (state: RootState) => state.projects.details,
  loading: (state: RootState) => state.projects.loading,
  detailsLoading: (state: RootState) => state.projects.detailsLoading,
  error: (state: RootState) => state.projects.error,
};

const projectReducer = projectsSlice.reducer;

export default projectReducer;
