import {
  IncrementalJumpHistoryResponse,
  IncrementalJumpPreviewResponse,
  IncrementalJumpProcessPayload,
  IncrementalJumpProcessResponse,
} from '@/interface/PayrollDataManagement';
import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { apiGet, apiPost } 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 { IncrementalJumpsActions } from './actionTypes';

interface IncrementalJumpsState {
  preview: IncrementalJumpPreviewResponse | null;
  history: IncrementalJumpHistoryResponse | null;
  loading: boolean;
  processing: boolean;
  error: string | null;
}

const initialState: IncrementalJumpsState = {
  preview: null,
  history: null,
  loading: false,
  processing: false,
  error: null,
};

export const fetchIncrementalJumpPreview = createAsyncThunk(
  IncrementalJumpsActions.FETCH_PREVIEW,
  async (
    payload?: {
      effective_date?: string;
      employee_ids?: string[];
      include_ineligible?: boolean;
    },
    { rejectWithValue },
  ) => {
    try {
      const queryParams = new URLSearchParams();

      if (payload?.effective_date) {
        queryParams.append('effective_date', payload.effective_date);
      }

      if (payload?.employee_ids?.length) {
        payload.employee_ids.forEach((id) => queryParams.append('employee_ids[]', id));
      }

      if (payload?.include_ineligible) {
        queryParams.append('include_ineligible', '1');
      }

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

      const response = (await apiGet(
        `/payroll/incremental-jumps/preview${query}`,
      )) as AxiosResponse<IncrementalJumpPreviewResponse>;

      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const processIncrementalJump = createAsyncThunk(
  IncrementalJumpsActions.PROCESS_JUMP,
  async (payload: IncrementalJumpProcessPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/payroll/incremental-jumps/process', payload)) as AxiosResponse<
        IncrementalJumpProcessResponse
      >;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const fetchIncrementalJumpHistory = createAsyncThunk(
  IncrementalJumpsActions.FETCH_HISTORY,
  async (
    params?: {
      employee_id?: string;
      year?: number;
      per_page?: number;
    },
    { rejectWithValue },
  ) => {
    try {
      const queryParams = new URLSearchParams();

      if (params?.employee_id) {
        queryParams.append('employee_id', params.employee_id);
      }

      if (params?.year) {
        queryParams.append('year', String(params.year));
      }

      if (params?.per_page) {
        queryParams.append('per_page', String(params.per_page));
      }

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

      const response = (await apiGet(
        `/payroll/incremental-jumps/history${query}`,
      )) as AxiosResponse<IncrementalJumpHistoryResponse>;

      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const IncrementalJumpsSlice = createSlice({
  name: 'incrementalJumps',
  initialState,
  reducers: {
    clearIncrementalJumpPreview(state) {
      state.preview = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchIncrementalJumpPreview.pending, (state: Draft<IncrementalJumpsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchIncrementalJumpPreview.fulfilled,
        (state: Draft<IncrementalJumpsState>, action: PayloadAction<IncrementalJumpPreviewResponse>) => {
          state.loading = false;
          state.preview = action.payload;
          state.error = null;
        },
      )
      .addCase(
        fetchIncrementalJumpPreview.rejected,
        (state: Draft<IncrementalJumpsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );

    builder
      .addCase(processIncrementalJump.pending, (state: Draft<IncrementalJumpsState>) => {
        state.processing = true;
        state.error = null;
      })
      .addCase(
        processIncrementalJump.fulfilled,
        (state: Draft<IncrementalJumpsState>, action: PayloadAction<IncrementalJumpProcessResponse>) => {
          state.processing = false;
          state.error = null;
          message.success(action.payload.message || 'Incremental jump processed successfully');
        },
      )
      .addCase(
        processIncrementalJump.rejected,
        (state: Draft<IncrementalJumpsState>, action: RejectedActionPayload) => {
          state.processing = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );

    builder
      .addCase(fetchIncrementalJumpHistory.pending, (state: Draft<IncrementalJumpsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchIncrementalJumpHistory.fulfilled,
        (state: Draft<IncrementalJumpsState>, action: PayloadAction<IncrementalJumpHistoryResponse>) => {
          state.loading = false;
          state.history = action.payload;
          state.error = null;
        },
      )
      .addCase(
        fetchIncrementalJumpHistory.rejected,
        (state: Draft<IncrementalJumpsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );
  },
});

export const { clearIncrementalJumpPreview } = IncrementalJumpsSlice.actions;

export default IncrementalJumpsSlice;
