import { EmployeeRequestActionResponse, PendingRequestApproval } from '@/interface/EmployeeRequest';
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 { RequestApprovalsActions } from './actionTypes';

interface RequestApprovalsState {
  pendingApprovals: PendingRequestApproval[];
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

const initialState: RequestApprovalsState = {
  pendingApprovals: [],
  loading: false,
  actionLoading: false,
  error: null,
};

export const fetchPendingRequestApprovals = createAsyncThunk(
  RequestApprovalsActions.FETCH_PENDING_APPROVALS,
  async () => {
    const response = (await apiGet('/requests/approvals/pending')) as AxiosResponse<
      PendingRequestApproval[] | { data: PendingRequestApproval[] }
    >;
    return Array.isArray(response.data) ? response.data : response.data.data;
  },
);

export const approveEmployeeRequest = createAsyncThunk(
  RequestApprovalsActions.APPROVE_REQUEST,
  async ({ id, comments }: { id: string; comments?: string }, { rejectWithValue }) => {
    try {
      const response = (await apiPost(`/requests/approvals/${id}/approve`, {
        comments,
      })) as AxiosResponse<EmployeeRequestActionResponse>;
      return { approvalId: id, response: response.data };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const rejectEmployeeRequest = createAsyncThunk(
  RequestApprovalsActions.REJECT_REQUEST,
  async ({ id, comments }: { id: string; comments: string }, { rejectWithValue }) => {
    try {
      const response = (await apiPost(`/requests/approvals/${id}/reject`, {
        comments,
      })) as AxiosResponse<EmployeeRequestActionResponse>;
      return { approvalId: id, response: response.data };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const RequestApprovalsSlice = createSlice({
  name: 'requestApprovals',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchPendingRequestApprovals.pending, (state: Draft<RequestApprovalsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPendingRequestApprovals.fulfilled,
        (state: Draft<RequestApprovalsState>, action: PayloadAction<PendingRequestApproval[]>) => {
          state.pendingApprovals = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchPendingRequestApprovals.rejected, (state: Draft<RequestApprovalsState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(approveEmployeeRequest.pending, (state: Draft<RequestApprovalsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        approveEmployeeRequest.fulfilled,
        (
          state: Draft<RequestApprovalsState>,
          action: PayloadAction<{ approvalId: string; response: EmployeeRequestActionResponse }>,
        ) => {
          state.actionLoading = false;
          state.error = null;
          state.pendingApprovals = state.pendingApprovals.filter((item) => item.id !== action.payload.approvalId);
          message.success(action.payload.response.message || 'Request approved successfully.');
        },
      )
      .addCase(approveEmployeeRequest.rejected, (state: Draft<RequestApprovalsState>, action: RejectedActionPayload) => {
        state.actionLoading = false;
        state.error = Helpers.handleServerError(action.payload);
        message.error(state.error, 10);
      });

    builder
      .addCase(rejectEmployeeRequest.pending, (state: Draft<RequestApprovalsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        rejectEmployeeRequest.fulfilled,
        (
          state: Draft<RequestApprovalsState>,
          action: PayloadAction<{ approvalId: string; response: EmployeeRequestActionResponse }>,
        ) => {
          state.actionLoading = false;
          state.error = null;
          state.pendingApprovals = state.pendingApprovals.filter((item) => item.id !== action.payload.approvalId);
          message.success(action.payload.response.message || 'Request rejected.');
        },
      )
      .addCase(rejectEmployeeRequest.rejected, (state: Draft<RequestApprovalsState>, action: RejectedActionPayload) => {
        state.actionLoading = false;
        state.error = Helpers.handleServerError(action.payload);
        message.error(state.error, 10);
      });
  },
});

export default RequestApprovalsSlice;
export type { RequestApprovalsState };
