import { configureStore } from '@reduxjs/toolkit';
import PartPaymentsSlice, {
  fetchPartPayments,
  createPartPayments,
  clearPartPayments,
} from '../PartPaymentsSlice';

jest.mock('@/services/api/api', () => ({
  apiGet: jest.fn(),
  apiPost: jest.fn(),
}));

jest.mock('antd', () => ({
  message: { success: jest.fn(), error: jest.fn(), warning: jest.fn() },
}));

jest.mock('@/utilities/Helpers', () => {
  const mockHelpers = { handleServerError: jest.fn((e: any) => e?.message || 'Error') };
  return { __esModule: true, default: mockHelpers };
});

const { apiGet, apiPost } = require('@/services/api/api');

const createTestStore = () =>
  configureStore({ reducer: { partPayments: PartPaymentsSlice.reducer } });

const mockPayment = { id: '1', employee_id: 'e1', amount: 2000 };

describe('PartPaymentsSlice', () => {
  beforeEach(() => jest.clearAllMocks());

  it('has correct initial state', () => {
    const store = createTestStore();
    const state = store.getState().partPayments;
    expect(state.payments).toEqual([]);
    expect(state.summary).toBeNull();
    expect(state.loading).toBe(false);
    expect(state.submitting).toBe(false);
    expect(state.error).toBeNull();
  });

  describe('fetchPartPayments', () => {
    it('populates payments and computes summary on fulfilled', async () => {
      apiGet.mockResolvedValue({ data: [mockPayment] });
      const store = createTestStore();
      await store.dispatch(fetchPartPayments('run1'));
      const state = store.getState().partPayments;
      expect(state.payments).toEqual([mockPayment]);
      expect(state.summary).toEqual({
        employee_count: 1,
        payment_count: 1,
        total_amount: 2000,
      });
    });

    it('handles wrapped response format', async () => {
      apiGet.mockResolvedValue({ data: { data: [mockPayment] } });
      const store = createTestStore();
      await store.dispatch(fetchPartPayments('run1'));
      expect(store.getState().partPayments.payments).toEqual([mockPayment]);
    });
  });

  describe('createPartPayments', () => {
    it('sets submitting on pending and populates on fulfilled', async () => {
      const response = {
        data: [mockPayment],
        summary: { employee_count: 1, payment_count: 1, total_amount: 2000 },
      };
      apiPost.mockResolvedValue({ data: response });
      const store = createTestStore();
      const promise = store.dispatch(createPartPayments({ payroll_run_id: 'r1' } as any));
      expect(store.getState().partPayments.submitting).toBe(true);
      await promise;
      expect(store.getState().partPayments.submitting).toBe(false);
      expect(store.getState().partPayments.payments).toEqual([mockPayment]);
    });
  });

  describe('clearPartPayments', () => {
    it('clears payments and summary', () => {
      const store = createTestStore();
      store.dispatch({
        type: fetchPartPayments.fulfilled.type,
        payload: [mockPayment],
      });
      store.dispatch(clearPartPayments());
      expect(store.getState().partPayments.payments).toEqual([]);
      expect(store.getState().partPayments.summary).toBeNull();
    });
  });
});
