import {
  CreateLeaveEntitlementPayload,
  DeleteLeaveEntitlementPayload,
  EntitlementCarryForwardPayload,
  EntitlementCarryForwardResult,
  EntitlementSyncPayload,
  EntitlementSyncResult,
  LeaveEntitlement,
  LeaveEntitlementFilters,
  UpdateLeaveEntitlementPayload,
} from '@/interface/LeaveEntitlement';
import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { LeaveEntitlementsActions } from './actionTypes';

interface LeaveEntitlementsState {
  entitlements: LeaveEntitlement[];
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

const initialState: LeaveEntitlementsState = {
  entitlements: [],
  loading: false,
  actionLoading: false,
  error: null,
};

const buildQueryString = (filters?: LeaveEntitlementFilters): string => {
  if (!filters) {
    return '';
  }

  const params = new URLSearchParams();

  if (filters.year) {
    params.set('year', String(filters.year));
  }

  if (filters.leave_type_id) {
    params.set('leave_type_id', filters.leave_type_id);
  }

  if (filters.employee_category_id !== undefined) {
    params.set('employee_category_id', filters.employee_category_id || '');
  }

  const query = params.toString();
  return query ? `?${query}` : '';
};

const extractCollectionData = (payload: LeaveEntitlement[] | { data: LeaveEntitlement[] }): LeaveEntitlement[] => {
  return Array.isArray(payload) ? payload : payload.data;
};

export const fetchLeaveEntitlements = createAsyncThunk(
  LeaveEntitlementsActions.FETCH_LEAVE_ENTITLEMENTS_REQUEST,
  async (filters?: LeaveEntitlementFilters) => {
    const response = (await apiGet(
      `/leave/entitlements${buildQueryString(filters)}`,
    )) as AxiosResponse<LeaveEntitlement[] | { data: LeaveEntitlement[] }>;

    return extractCollectionData(response.data);
  },
);

export const createLeaveEntitlement = createAsyncThunk(
  LeaveEntitlementsActions.CREATE_LEAVE_ENTITLEMENT_REQUEST,
  async (payload: CreateLeaveEntitlementPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/leave/entitlements', payload)) as AxiosResponse<{
        data: LeaveEntitlement;
      }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const updateLeaveEntitlement = createAsyncThunk(
  LeaveEntitlementsActions.UPDATE_LEAVE_ENTITLEMENT_REQUEST,
  async (payload: UpdateLeaveEntitlementPayload, { rejectWithValue }) => {
    try {
      const { id, ...data } = payload;
      const response = (await apiPut(`/leave/entitlements/${id}`, data)) as AxiosResponse<{
        data: LeaveEntitlement;
      }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const deleteLeaveEntitlement = createAsyncThunk(
  LeaveEntitlementsActions.DELETE_LEAVE_ENTITLEMENT_REQUEST,
  async (id: string) => {
    const response = (await apiDelete(`/leave/entitlements/${id}`)) as AxiosResponse<DeleteLeaveEntitlementPayload>;
    const responseData = response.data;
    responseData.id = id;
    return responseData;
  },
);

export const syncBalances = createAsyncThunk(
  LeaveEntitlementsActions.SYNC_BALANCES_REQUEST,
  async (payload: EntitlementSyncPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/leave/entitlements/sync', payload)) as AxiosResponse<EntitlementSyncResult>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const carryForwardBalances = createAsyncThunk(
  LeaveEntitlementsActions.CARRY_FORWARD_BALANCES_REQUEST,
  async (payload: EntitlementCarryForwardPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/leave/entitlements/carry-forward',
        payload,
      )) as AxiosResponse<EntitlementCarryForwardResult>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const LeaveEntitlementsSlice = createSlice({
  name: 'leaveEntitlements',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchLeaveEntitlements.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchLeaveEntitlements.fulfilled,
        (state: Draft<LeaveEntitlementsState>, action: PayloadAction<LeaveEntitlement[]>) => {
          state.entitlements = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchLeaveEntitlements.rejected, (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error =
          'Failed to load leave entitlements. Please try again or contact support if the issue persists';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createLeaveEntitlement.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        createLeaveEntitlement.fulfilled,
        (state: Draft<LeaveEntitlementsState>, action: PayloadAction<LeaveEntitlement>) => {
          state.entitlements.unshift(action.payload);
          state.actionLoading = false;
          state.error = null;
          message.success('Leave entitlement created successfully');
        },
      )
      .addCase(
        createLeaveEntitlement.rejected,
        (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );

    builder
      .addCase(updateLeaveEntitlement.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        updateLeaveEntitlement.fulfilled,
        (state: Draft<LeaveEntitlementsState>, action: PayloadAction<LeaveEntitlement>) => {
          const index = state.entitlements.findIndex((item) => item.id === action.payload.id);
          if (index !== -1) {
            state.entitlements[index] = action.payload;
          }
          state.actionLoading = false;
          state.error = null;
          message.success('Leave entitlement updated successfully');
        },
      )
      .addCase(
        updateLeaveEntitlement.rejected,
        (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );

    builder
      .addCase(deleteLeaveEntitlement.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = true;
      })
      .addCase(
        deleteLeaveEntitlement.fulfilled,
        (state: Draft<LeaveEntitlementsState>, action: PayloadAction<DeleteLeaveEntitlementPayload>) => {
          state.entitlements = state.entitlements.filter((item) => item.id !== action.payload.id);
          state.actionLoading = false;
          state.error = null;
          message.success(action.payload.message);
        },
      )
      .addCase(deleteLeaveEntitlement.rejected, (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
        state.actionLoading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(syncBalances.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(syncBalances.fulfilled, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = false;
      })
      .addCase(syncBalances.rejected, (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
        state.actionLoading = false;
        state.error = Helpers.handleServerError(action.payload);
        message.error(state.error, 10);
      });

    builder
      .addCase(carryForwardBalances.pending, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(carryForwardBalances.fulfilled, (state: Draft<LeaveEntitlementsState>) => {
        state.actionLoading = false;
      })
      .addCase(
        carryForwardBalances.rejected,
        (state: Draft<LeaveEntitlementsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );
  },
});

export default LeaveEntitlementsSlice;
export type { LeaveEntitlementsState };
