import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  CreateLoanPayload,
  CreateLoanRepaymentPayload,
  Loan,
  LoanRepayment,
  DeleteLoanPayload,
  UpdateLoanPayload,
} from '@/interface/Loan';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { LoansActions } from './actionTypes';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface LoanState {
  loans: Loan[];
  selectedLoan: Loan | null;
  loading: boolean;
  error: string | null;
}

const initialState: LoanState = {
  loans: [],
  selectedLoan: null,
  loading: false,
  error: null,
};

export const fetchLoans = createAsyncThunk(
  LoansActions.FETCH_LOANS_REQUEST,
  async (params?: {
    employee_id?: string;
    status?: string;
    loan_type?: string;
    branch_id?: string;
  }) => {
    const queryParams = new URLSearchParams();
    if (params?.employee_id) queryParams.append('employee_id', params.employee_id);
    if (params?.status) queryParams.append('status', params.status);
    if (params?.loan_type) queryParams.append('loan_type', params.loan_type);
    if (params?.branch_id) queryParams.append('branch_id', params.branch_id);
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(`/payroll/loans${query}`)) as AxiosResponse<Loan[]>;
    return response.data;
  },
);

export const fetchLoan = createAsyncThunk(
  LoansActions.FETCH_LOAN_REQUEST,
  async (id: string) => {
    const response = (await apiGet(`/payroll/loans/${id}`)) as AxiosResponse<Loan>;
    return response.data;
  },
);

export const createLoan = createAsyncThunk(
  LoansActions.CREATE_LOAN_REQUEST,
  async (payload: CreateLoanPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/payroll/loans', payload)) as AxiosResponse<{
        data: Loan;
      }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateLoan = createAsyncThunk(
  LoansActions.UPDATE_LOAN_REQUEST,
  async (payload: UpdateLoanPayload, { rejectWithValue }) => {
    try {
      const { id, ...data } = payload;
      const response = (await apiPut(`/payroll/loans/${id}`, data)) as AxiosResponse<{
        data: Loan;
      }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteLoan = createAsyncThunk(
  LoansActions.DELETE_LOAN_REQUEST,
  async (id: string) => {
    const response = (await apiDelete(`/payroll/loans/${id}`)) as AxiosResponse<DeleteLoanPayload>;
    const responseData = response.data;
    responseData.id = id;
    return responseData;
  },
);

export const recordRepayment = createAsyncThunk(
  LoansActions.RECORD_REPAYMENT_REQUEST,
  async (payload: CreateLoanRepaymentPayload, { rejectWithValue }) => {
    try {
      const { loan_id, ...data } = payload;
      const response = (await apiPost(
        `/payroll/loans/${loan_id}/repayments`,
        data,
      )) as AxiosResponse<{ data: LoanRepayment }>;
      return { loan_id, repayment: response.data.data };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const LoansSlice = createSlice({
  name: 'loans',
  initialState,
  reducers: {
    clearSelectedLoan(state) {
      state.selectedLoan = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchLoans.pending, (state: Draft<LoanState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchLoans.fulfilled,
        (state: Draft<LoanState>, action: PayloadAction<Loan[]>) => {
          state.loans = action.payload;
          state.error = null;
          state.loading = false;
        },
      )
      .addCase(fetchLoans.rejected, (state: Draft<LoanState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load loans. Please try again or contact support';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(fetchLoan.pending, (state: Draft<LoanState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchLoan.fulfilled,
        (state: Draft<LoanState>, action: PayloadAction<Loan>) => {
          state.selectedLoan = action.payload;
          state.error = null;
          state.loading = false;
        },
      )
      .addCase(fetchLoan.rejected, (state: Draft<LoanState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load loan details. Please try again or contact support';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createLoan.pending, (state: Draft<LoanState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        createLoan.fulfilled,
        (state: Draft<LoanState>, action: PayloadAction<Loan>) => {
          state.loans.unshift(action.payload);
          state.error = null;
          state.loading = false;
          message.success('Loan created successfully');
        },
      )
      .addCase(
        createLoan.rejected,
        (state: Draft<LoanState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updateLoan.pending, (state: Draft<LoanState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        updateLoan.fulfilled,
        (state: Draft<LoanState>, action: PayloadAction<Loan>) => {
          const index = state.loans.findIndex((l) => l.id === action.payload.id);
          if (index !== -1) {
            state.loans[index] = action.payload;
          }
          if (state.selectedLoan?.id === action.payload.id) {
            state.selectedLoan = action.payload;
          }
          state.loading = false;
          state.error = null;
          message.success('Loan updated successfully');
        },
      )
      .addCase(
        updateLoan.rejected,
        (state: Draft<LoanState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteLoan.pending, (state: Draft<LoanState>) => {
        state.loading = true;
      })
      .addCase(
        deleteLoan.fulfilled,
        (state: Draft<LoanState>, action: PayloadAction<DeleteLoanPayload>) => {
          state.loans = state.loans.filter((l) => l.id !== action.payload.id);
          state.loading = false;
          message.success(action.payload.message);
        },
      )
      .addCase(deleteLoan.rejected, (state: Draft<LoanState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to delete loan. Please try again or contact support';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(recordRepayment.pending, (state: Draft<LoanState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(recordRepayment.fulfilled, (state: Draft<LoanState>) => {
        state.loading = false;
        state.error = null;
        message.success('Loan repayment recorded successfully');
      })
      .addCase(
        recordRepayment.rejected,
        (state: Draft<LoanState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export const { clearSelectedLoan } = LoansSlice.actions;
export default LoansSlice;
export type { LoanState };
