import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  CreateProvidentFundEnrollmentPayload,
  ProvidentFundOverride,
  ProvidentFundPaginatedResponse,
  UpdateProvidentFundOverridePayload,
  BulkUpdateProvidentFundPayload,
} from '@/interface/ProvidentFundOverride';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { ProvidentFundOverridesActions } from './actionTypes';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface ProvidentFundOverrideState {
  overrides: ProvidentFundOverride[];
  loading: boolean;
  error: string | null;
  meta: {
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
  } | null;
}

const initialState: ProvidentFundOverrideState = {
  overrides: [],
  loading: false,
  error: null,
  meta: null,
};

export const fetchProvidentFundOverrides = createAsyncThunk(
  ProvidentFundOverridesActions.FETCH_PROVIDENT_FUND_OVERRIDES_REQUEST,
  async (params?: { per_page?: number; page?: number; branch_id?: string }) => {
    const queryParams = new URLSearchParams();
    if (params?.per_page) queryParams.append('per_page', String(params.per_page));
    if (params?.page) queryParams.append('page', String(params.page));
    if (params?.branch_id) queryParams.append('branch_id', params.branch_id);
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(`/payroll/provident-fund${query}`)) as AxiosResponse<
      ProvidentFundPaginatedResponse | ProvidentFundOverride[]
    >;

    if (Array.isArray(response.data)) {
      return { data: response.data, meta: null };
    }
    return response.data;
  },
);

export const createProvidentFundEnrollment = createAsyncThunk(
  ProvidentFundOverridesActions.CREATE_PROVIDENT_FUND_ENROLLMENT_REQUEST,
  async (payload: CreateProvidentFundEnrollmentPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/payroll/provident-fund',
        payload,
      )) as AxiosResponse<{ data: ProvidentFundOverride }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateProvidentFundOverride = createAsyncThunk(
  ProvidentFundOverridesActions.UPDATE_PROVIDENT_FUND_OVERRIDE_REQUEST,
  async (payload: UpdateProvidentFundOverridePayload, { rejectWithValue }) => {
    try {
      const { employee_id, ...data } = payload;
      const response = (await apiPut(
        `/payroll/employees/${employee_id}/provident-fund`,
        data,
      )) as AxiosResponse<{ data: ProvidentFundOverride }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteProvidentFundEnrollment = createAsyncThunk(
  ProvidentFundOverridesActions.DELETE_PROVIDENT_FUND_ENROLLMENT_REQUEST,
  async (id: string, { rejectWithValue }) => {
    try {
      await apiDelete(`/payroll/provident-fund/${id}`);
      return { id };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const bulkUpdateProvidentFund = createAsyncThunk(
  ProvidentFundOverridesActions.BULK_UPDATE_PROVIDENT_FUND_REQUEST,
  async (payload: BulkUpdateProvidentFundPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/payroll/provident-fund/bulk-update',
        payload,
      )) as AxiosResponse<{ message: string }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const ProvidentFundOverridesSlice = createSlice({
  name: 'providentFundOverrides',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchProvidentFundOverrides.pending, (state: Draft<ProvidentFundOverrideState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchProvidentFundOverrides.fulfilled,
        (
          state: Draft<ProvidentFundOverrideState>,
          action: PayloadAction<{
            data: ProvidentFundOverride[];
            meta: ProvidentFundOverrideState['meta'];
          }>,
        ) => {
          state.overrides = action.payload.data;
          state.meta = action.payload.meta;
          state.error = null;
          state.loading = false;
        },
      )
      .addCase(fetchProvidentFundOverrides.rejected, (state: Draft<ProvidentFundOverrideState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load provident fund overrides';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(
        createProvidentFundEnrollment.pending,
        (state: Draft<ProvidentFundOverrideState>) => {
          state.loading = true;
          state.error = null;
        },
      )
      .addCase(
        createProvidentFundEnrollment.fulfilled,
        (
          state: Draft<ProvidentFundOverrideState>,
          action: PayloadAction<ProvidentFundOverride>,
        ) => {
          state.overrides.unshift(action.payload);
          state.loading = false;
          state.error = null;
          message.success('Employee enrolled in provident fund successfully');
        },
      )
      .addCase(
        createProvidentFundEnrollment.rejected,
        (state: Draft<ProvidentFundOverrideState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(
        updateProvidentFundOverride.pending,
        (state: Draft<ProvidentFundOverrideState>) => {
          state.loading = true;
          state.error = null;
        },
      )
      .addCase(
        updateProvidentFundOverride.fulfilled,
        (
          state: Draft<ProvidentFundOverrideState>,
          action: PayloadAction<ProvidentFundOverride>,
        ) => {
          const index = state.overrides.findIndex((o) => o.id === action.payload.id);
          if (index !== -1) {
            state.overrides[index] = action.payload;
          } else {
            state.overrides.unshift(action.payload);
          }
          state.loading = false;
          state.error = null;
          message.success('Provident fund override updated successfully');
        },
      )
      .addCase(
        updateProvidentFundOverride.rejected,
        (state: Draft<ProvidentFundOverrideState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(
        deleteProvidentFundEnrollment.pending,
        (state: Draft<ProvidentFundOverrideState>) => {
          state.loading = true;
        },
      )
      .addCase(
        deleteProvidentFundEnrollment.fulfilled,
        (
          state: Draft<ProvidentFundOverrideState>,
          action: PayloadAction<{ id: string }>,
        ) => {
          state.overrides = state.overrides.filter((o) => o.id !== action.payload.id);
          state.loading = false;
          message.success('Employee unenrolled from provident fund');
        },
      )
      .addCase(
        deleteProvidentFundEnrollment.rejected,
        (state: Draft<ProvidentFundOverrideState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(
        bulkUpdateProvidentFund.pending,
        (state: Draft<ProvidentFundOverrideState>) => {
          state.loading = true;
          state.error = null;
        },
      )
      .addCase(
        bulkUpdateProvidentFund.fulfilled,
        (
          state: Draft<ProvidentFundOverrideState>,
          action: PayloadAction<{ message: string }>,
        ) => {
          state.loading = false;
          state.error = null;
          message.success(action.payload.message);
        },
      )
      .addCase(
        bulkUpdateProvidentFund.rejected,
        (state: Draft<ProvidentFundOverrideState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export default ProvidentFundOverridesSlice;
export type { ProvidentFundOverrideState };
