import {
  CreatePartPaymentPayload,
  CreatePartPaymentResponse,
  PartPayment,
  PartPaymentSummary,
} 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 { PartPaymentsActions } from './actionTypes';

interface PartPaymentsState {
  payments: PartPayment[];
  summary: PartPaymentSummary | null;
  loading: boolean;
  submitting: boolean;
  error: string | null;
}

const initialState: PartPaymentsState = {
  payments: [],
  summary: null,
  loading: false,
  submitting: false,
  error: null,
};

const resolveListPayload = (payload: unknown): PartPayment[] => {
  if (Array.isArray(payload)) {
    return payload as PartPayment[];
  }

  const data = (payload as { data?: PartPayment[] })?.data;
  return Array.isArray(data) ? data : [];
};

export const fetchPartPayments = createAsyncThunk(
  PartPaymentsActions.FETCH_PART_PAYMENTS,
  async (payrollRunId: string, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/payroll/part-payments/${payrollRunId}`,
      )) as AxiosResponse<PartPayment[] | { data: PartPayment[] }>;

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

      throw error;
    }
  },
);

export const createPartPayments = createAsyncThunk(
  PartPaymentsActions.CREATE_PART_PAYMENTS,
  async (payload: CreatePartPaymentPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/payroll/part-payments', payload)) as AxiosResponse<
        CreatePartPaymentResponse
      >;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }

      throw error;
    }
  },
);

export const PartPaymentsSlice = createSlice({
  name: 'partPayments',
  initialState,
  reducers: {
    clearPartPayments(state) {
      state.payments = [];
      state.summary = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchPartPayments.pending, (state: Draft<PartPaymentsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPartPayments.fulfilled,
        (state: Draft<PartPaymentsState>, action: PayloadAction<PartPayment[]>) => {
          state.loading = false;
          state.payments = action.payload;
          state.summary = {
            employee_count: new Set(action.payload.map((item) => item.employee_id)).size,
            payment_count: action.payload.length,
            total_amount: action.payload.reduce((sum, current) => sum + Number(current.amount || 0), 0),
          };
          state.error = null;
        },
      )
      .addCase(
        fetchPartPayments.rejected,
        (state: Draft<PartPaymentsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );

    builder
      .addCase(createPartPayments.pending, (state: Draft<PartPaymentsState>) => {
        state.submitting = true;
        state.error = null;
      })
      .addCase(
        createPartPayments.fulfilled,
        (state: Draft<PartPaymentsState>, action: PayloadAction<CreatePartPaymentResponse>) => {
          state.submitting = false;
          state.payments = action.payload.data;
          state.summary = action.payload.summary;
          state.error = null;
          message.success('Part payment schedule created successfully');
        },
      )
      .addCase(
        createPartPayments.rejected,
        (state: Draft<PartPaymentsState>, action: RejectedActionPayload) => {
          state.submitting = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );
  },
});

export const { clearPartPayments } = PartPaymentsSlice.actions;

export default PartPaymentsSlice;
