import { configureStore } from '@reduxjs/toolkit';
import PayrollImportsSlice, {
  downloadImportTemplate,
  validatePayrollImport,
  executePayrollImport,
  fetchPayrollImportStatus,
  clearImportState,
} from '../PayrollImportsSlice';

jest.mock('@/services/api/api', () => ({
  apiGet: jest.fn(),
  apiPost: jest.fn(),
  apiDownloadBlob: jest.fn(),
  axiosInstance: { get: 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 createTestStore = () =>
  configureStore({ reducer: { payrollImports: PayrollImportsSlice.reducer } });

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

  it('has correct initial state', () => {
    const store = createTestStore();
    const state = store.getState().payrollImports;
    expect(state.validationResult).toBeNull();
    expect(state.importResult).toBeNull();
    expect(state.importBatch).toBeNull();
    expect(state.downloadingTemplate).toBe(false);
    expect(state.validating).toBe(false);
    expect(state.importing).toBe(false);
    expect(state.downloadingFailedRows).toBe(false);
    expect(state.error).toBeNull();
  });

  describe('downloadImportTemplate', () => {
    it('sets downloadingTemplate on pending', () => {
      const store = createTestStore();
      store.dispatch({ type: downloadImportTemplate.pending.type });
      expect(store.getState().payrollImports.downloadingTemplate).toBe(true);
    });

    it('clears downloadingTemplate on fulfilled', () => {
      const store = createTestStore();
      store.dispatch({ type: downloadImportTemplate.pending.type });
      store.dispatch({ type: downloadImportTemplate.fulfilled.type, payload: true });
      expect(store.getState().payrollImports.downloadingTemplate).toBe(false);
    });
  });

  describe('validatePayrollImport', () => {
    it('sets validating on pending and result on fulfilled', () => {
      const store = createTestStore();
      store.dispatch({ type: validatePayrollImport.pending.type });
      expect(store.getState().payrollImports.validating).toBe(true);
      const result = { message: 'Valid', type: 'grades', validate_only: true };
      store.dispatch({ type: validatePayrollImport.fulfilled.type, payload: result });
      expect(store.getState().payrollImports.validating).toBe(false);
      expect(store.getState().payrollImports.validationResult).toEqual(result);
    });
  });

  describe('executePayrollImport', () => {
    it('sets importing on pending and importBatch on fulfilled', () => {
      const store = createTestStore();
      store.dispatch({ type: executePayrollImport.pending.type });
      expect(store.getState().payrollImports.importing).toBe(true);
      const batchResponse = { batch_id: 'b1', message: 'Started' };
      store.dispatch({ type: executePayrollImport.fulfilled.type, payload: batchResponse });
      expect(store.getState().payrollImports.importing).toBe(false);
      expect(store.getState().payrollImports.importBatch?.batch_id).toBe('b1');
    });
  });

  describe('fetchPayrollImportStatus', () => {
    it('updates importBatch on fulfilled', () => {
      const store = createTestStore();
      const status = { batch_id: 'b1', finished: true, progress: 100, error: null };
      store.dispatch({ type: fetchPayrollImportStatus.fulfilled.type, payload: status });
      expect(store.getState().payrollImports.importBatch).toEqual(status);
    });
  });

  describe('clearImportState', () => {
    it('resets import-related state', () => {
      const store = createTestStore();
      store.dispatch({ type: validatePayrollImport.fulfilled.type, payload: { message: 'ok' } });
      store.dispatch(clearImportState());
      const state = store.getState().payrollImports;
      expect(state.validationResult).toBeNull();
      expect(state.importResult).toBeNull();
      expect(state.importBatch).toBeNull();
      expect(state.error).toBeNull();
    });
  });
});
