import { configureStore } from '@reduxjs/toolkit';
import { OrganisationUnitSlice, fetchOrganisationUnits, fetchOrganisationUnit, createOrganisationUnit, updateOrganisationUnit, deleteOrganisationUnit, clearOrganisationUnit, updateUnitHead } from '../OrganisationUnitSlice';

jest.mock('@/services/api/api', () => ({
  apiGet: jest.fn(),
  apiPost: jest.fn(),
  apiPut: jest.fn(),
  apiDelete: 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 createStore = () => configureStore({ reducer: { orgUnits: OrganisationUnitSlice.reducer } });

describe('OrganisationUnitSlice', () => {
  it('has correct initial state', () => {
    const store = createStore();
    const state = store.getState().orgUnits;
    expect(state.organisationUnits).toEqual([]);
    expect(state.organisationUnit).toBeNull();
    expect(state.loadingUnits).toBe(false);
    expect(state.error).toBeNull();
  });

  describe('reducers', () => {
    it('clearOrganisationUnit resets organisationUnit', () => {
      const store = createStore();
      store.dispatch({ type: fetchOrganisationUnit.fulfilled.type, payload: { id: 'u1' } });
      store.dispatch(clearOrganisationUnit());
      expect(store.getState().orgUnits.organisationUnit).toBeNull();
    });
  });

  describe('fetchOrganisationUnits', () => {
    it('sets loadingUnits on pending', () => {
      const store = createStore();
      store.dispatch({ type: fetchOrganisationUnits.pending.type });
      expect(store.getState().orgUnits.loadingUnits).toBe(true);
    });

    it('populates units on fulfilled', () => {
      const store = createStore();
      const units = [{ id: 'u1', name: 'IT' }];
      store.dispatch({ type: fetchOrganisationUnits.fulfilled.type, payload: units });
      expect(store.getState().orgUnits.organisationUnits).toEqual(units);
      expect(store.getState().orgUnits.loadingUnits).toBe(false);
    });
  });

  describe('createOrganisationUnit', () => {
    it('prepends unit on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchOrganisationUnits.fulfilled.type, payload: [{ id: 'u1' }] });
      store.dispatch({ type: createOrganisationUnit.fulfilled.type, payload: { id: 'u2', name: 'HR' } });
      expect(store.getState().orgUnits.organisationUnits[0].id).toBe('u2');
    });
  });

  describe('deleteOrganisationUnit', () => {
    it('removes unit on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchOrganisationUnits.fulfilled.type, payload: [{ id: 'u1' }, { id: 'u2' }] });
      store.dispatch({ type: deleteOrganisationUnit.fulfilled.type, payload: { id: 'u1', message: 'Deleted' } });
      expect(store.getState().orgUnits.organisationUnits).toHaveLength(1);
    });
  });

  describe('updateOrganisationUnit', () => {
    it('sets loadingUnits false on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: updateOrganisationUnit.pending.type });
      expect(store.getState().orgUnits.loadingUnits).toBe(true);
      store.dispatch({ type: updateOrganisationUnit.fulfilled.type, payload: { id: 'u1', name: 'Finance' } });
      expect(store.getState().orgUnits.loadingUnits).toBe(false);
    });

    it('sets loadingUnits false on rejected', () => {
      const store = createStore();
      store.dispatch({ type: updateOrganisationUnit.pending.type });
      expect(store.getState().orgUnits.loadingUnits).toBe(true);
      store.dispatch({ type: updateOrganisationUnit.rejected.type, payload: { message: 'Update failed' } });
      expect(store.getState().orgUnits.loadingUnits).toBe(false);
    });
  });

  describe('updateUnitHead', () => {
    it('updates the unit in the list on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchOrganisationUnits.fulfilled.type, payload: [{ id: 'u1', head_id: null }] });
      store.dispatch({ type: updateUnitHead.fulfilled.type, payload: { id: 'u1', head_id: 'e1' } });
      expect(store.getState().orgUnits.organisationUnits[0].head_id).toBe('e1');
    });
  });
});
