import { ApprovalActionPayload, LeaveApprovalFilters, PendingLeaveApproval } from '@/interface/LeaveApproval';
import { LeaveRequestActionResponse } from '@/interface/LeaveRequest';
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 { LeaveApprovalsActions } from './actionTypes';

interface LeaveApprovalsState {
  pendingApprovals: PendingLeaveApproval[];
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

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

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

  const params = new URLSearchParams();

  if (filters.employee_id) params.set('employee_id', filters.employee_id);
  if (filters.leave_type_id) params.set('leave_type_id', filters.leave_type_id);
  if (filters.year) params.set('year', String(filters.year));
  if (filters.branch_id) params.set('branch_id', filters.branch_id);
  if (filters.date_from) params.set('date_from', filters.date_from);
  if (filters.date_to) params.set('date_to', filters.date_to);
  if (filters.search) params.set('search', filters.search);
  if (filters.per_page) params.set('per_page', String(filters.per_page));

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

export const fetchPendingApprovals = createAsyncThunk(
  LeaveApprovalsActions.FETCH_PENDING_APPROVALS_REQUEST,
  async (filters?: LeaveApprovalFilters) => {
    const response = (await apiGet(
      `/leave/approvals/pending${buildQueryString(filters)}`,
    )) as AxiosResponse<PendingLeaveApproval[] | { data: PendingLeaveApproval[] }>;

    return Array.isArray(response.data) ? response.data : response.data.data;
  },
);

export const approveLeaveRequest = createAsyncThunk(
  LeaveApprovalsActions.APPROVE_LEAVE_REQUEST_REQUEST,
  async ({ id, comments }: ApprovalActionPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(`/leave/approvals/${id}/approve`, {
        comments,
      })) as AxiosResponse<LeaveRequestActionResponse>;

      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 rejectLeaveRequest = createAsyncThunk(
  LeaveApprovalsActions.REJECT_LEAVE_REQUEST_REQUEST,
  async ({ id, comments }: ApprovalActionPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(`/leave/approvals/${id}/reject`, {
        comments,
      })) as AxiosResponse<LeaveRequestActionResponse>;

      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 LeaveApprovalsSlice = createSlice({
  name: 'leaveApprovals',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchPendingApprovals.pending, (state: Draft<LeaveApprovalsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPendingApprovals.fulfilled,
        (state: Draft<LeaveApprovalsState>, action: PayloadAction<PendingLeaveApproval[]>) => {
          state.pendingApprovals = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchPendingApprovals.rejected, (state: Draft<LeaveApprovalsState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

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

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

export default LeaveApprovalsSlice;
export type { LeaveApprovalsState };
