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 { employeesApi } from "../../../config/apiUrls/apiUrl";
import { OK } from "../../../config/axois/apiStatusCode";
import { errorHandler, isEmpty } from "../../../helper/helper";

export interface Employee {
  id: string | number;
  first_name: string;
  last_name: string;
  phone_no: string;
  email: string;
  password: string | null;
  pay_per_hour: string | null;
  is_active: boolean;
  total_working_duration?: string | null;
}

interface EmployeeListing {
  id: string | number;
  full_name: string;
  phone_no: string;
  email: string;
  password: string | null;
  pay_per_hour: string | null;
  is_active: boolean;
  total_working_duration?: string | null;
  deleted_at?: string | null;
  total_amount?: string | null;
}

interface EmployeesState {
  employees: EmployeeListing[];
  details: Employee | null;
  loading: boolean;
  detailsLoading: boolean;
  error: string | null;
}

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

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

interface AssignProjects {
  id: number;
  project_id: number[];
}

export const fetchEmployees: any = createAsyncThunk(
  "employees/fetchEmployees",
  async ({
    currentOffset,
    limit,
    search,
    ordering,
    projectId,
    is_active,
    include_all_employees,
    isDeleted,
  }: QueryParam) => {
    try {
      let url = `${
        employeesApi.getEmployees
      }?limit=${limit}&offset=${currentOffset}&search=${
        isEmpty(search) ? "" : search
      }&ordering=${isEmpty(ordering) ? "" : ordering}`;

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

      if (is_active) {
        url += `&is_active=${is_active}`;
      }

      if (include_all_employees === true) {
        url += `&include_all_employees=${include_all_employees}`;
      }

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

      const response = await getRequest(url, true);

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

export const createEmployee = createAsyncThunk(
  "employees/createEmployee",
  async (newEmployee: Omit<Employee, "id">) => {
    // Omitting "id" from newEmployee
    try {
      const response = await postRequest(
        employeesApi.createEmployee,
        newEmployee,
        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 updateEmployee = createAsyncThunk(
  "employees/updateEmployee",
  async (updatedEmployee: Employee) => {
    try {
      const response = await patchRequest(
        employeesApi.updateEmployee + updatedEmployee.id,
        updatedEmployee,
        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 getEmployeeById = createAsyncThunk(
  "employees/getEmployeeById",
  async (employeeId: any) => {
    try {
      const response = await getRequest(
        `${employeesApi.getEmployees}/${employeeId}`,
        true
      );

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

export const assignProjects = createAsyncThunk(
  "employees/assignProject",
  async (assignProject: AssignProjects) => {
    try {
      const response = await postRequest(
        `${employeesApi.getEmployees}/${assignProject.id}/assign-project`,
        { project_id: assignProject.project_id },
        true
      );

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

      return error;
    }
  }
);

export const unAssignProjects = createAsyncThunk(
  "employees/unAssignProject",
  async (assignProject: AssignProjects) => {
    try {
      const response = await postRequest(
        `${employeesApi.getEmployees}/${assignProject.id}/unassign-project`,
        { project_id: assignProject.project_id },
        true
      );

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

      return error;
    }
  }
);

const employeeSlice = createSlice({
  name: "clients",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchEmployees.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchEmployees.fulfilled, (state, action) => {
        state.loading = false;
        state.employees = action?.payload?.data?.data ?? {};
      })
      .addCase(fetchEmployees.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || "Failed to fetch employees";
      })
      .addCase(createEmployee.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Employee Added Successfully");
        }
      })
      .addCase(updateEmployee.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Employee Updated Successfully");
        }
      })
      .addCase(getEmployeeById.pending, (state) => {
        state.detailsLoading = true;
        state.error = null;
      })
      .addCase(getEmployeeById.fulfilled, (state, action) => {
        state.detailsLoading = false;
        state.details = action?.payload?.data?.data ?? null;
      })
      .addCase(getEmployeeById.rejected, (state, action) => {
        state.detailsLoading = false;
        state.error = action.error.message || "Failed to fetch employee";
      })
      .addCase(assignProjects.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Projects Assigned Successfully");
        }
      })
      .addCase(unAssignProjects.fulfilled, (state, action) => {
        if ([200, 201].includes(action?.payload?.status)) {
          showSuccess("Project Unassigned Successfully");
        }
      });
  },
});

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

const employeeReducer = employeeSlice.reducer;

export default employeeReducer;
