import { configureStore } from '@reduxjs/toolkit';
import GrievanceSlice, { fetchGrievances, fetchGrievance, createGrievance, updateGrievance, deleteGrievance, fetchGrievanceDocuments, uploadGrievanceDocument, deleteGrievanceDocument, fetchGrievanceTimeline, fetchGrievanceHearings, createGrievanceHearing, fetchGrievanceStats, clearGrievanceState } from '../GrievanceSlice';

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', () => ({
  default: { handleServerError: jest.fn((e) => e?.message || 'Error') },
}));

const createStore = () => configureStore({ reducer: { grievances: GrievanceSlice.reducer } });

describe('GrievanceSlice', () => {
  it('has correct initial state', () => {
    const store = createStore();
    const state = store.getState().grievances;
    expect(state.grievances).toEqual([]);
    expect(state.grievance).toBeNull();
    expect(state.documents).toEqual([]);
    expect(state.timeline).toEqual([]);
    expect(state.hearings).toEqual([]);
    expect(state.stats).toBeNull();
    expect(state.loading).toBe(false);
    expect(state.documentsLoading).toBe(false);
    expect(state.hearingsLoading).toBe(false);
    expect(state.timelineLoading).toBe(false);
    expect(state.statsLoading).toBe(false);
    expect(state.error).toBeNull();
  });

  describe('reducers', () => {
    it('clearGrievanceState resets detail fields', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievance.fulfilled.type, payload: { id: 'g1' } });
      store.dispatch(clearGrievanceState());
      const state = store.getState().grievances;
      expect(state.grievance).toBeNull();
      expect(state.documents).toEqual([]);
      expect(state.timeline).toEqual([]);
      expect(state.hearings).toEqual([]);
    });
  });

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

    it('populates grievances on fulfilled', () => {
      const store = createStore();
      const grievances = [{ id: 'g1', subject: 'Test' }];
      store.dispatch({ type: fetchGrievances.fulfilled.type, payload: grievances });
      expect(store.getState().grievances.grievances).toEqual(grievances);
      expect(store.getState().grievances.loading).toBe(false);
    });
  });

  describe('fetchGrievance', () => {
    it('sets grievance on fulfilled', () => {
      const store = createStore();
      const grievance = { id: 'g1', subject: 'Test' };
      store.dispatch({ type: fetchGrievance.fulfilled.type, payload: grievance });
      expect(store.getState().grievances.grievance).toEqual(grievance);
    });
  });

  describe('createGrievance', () => {
    it('prepends grievance and sets current on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievances.fulfilled.type, payload: [{ id: 'g1' }] });
      store.dispatch({ type: createGrievance.fulfilled.type, payload: { id: 'g2', subject: 'New' } });
      expect(store.getState().grievances.grievances[0].id).toBe('g2');
      expect(store.getState().grievances.grievance?.id).toBe('g2');
    });
  });

  describe('updateGrievance', () => {
    it('updates grievance in list on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievances.fulfilled.type, payload: [{ id: 'g1', subject: 'Old' }] });
      store.dispatch({ type: updateGrievance.fulfilled.type, payload: { id: 'g1', subject: 'Updated' } });
      expect(store.getState().grievances.grievances[0].subject).toBe('Updated');
      expect(store.getState().grievances.grievance?.subject).toBe('Updated');
    });
  });

  describe('deleteGrievance', () => {
    it('removes grievance from list on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievances.fulfilled.type, payload: [{ id: 'g1' }, { id: 'g2' }] });
      store.dispatch({ type: deleteGrievance.fulfilled.type, payload: { id: 'g1', message: 'Deleted' } });
      expect(store.getState().grievances.grievances).toHaveLength(1);
    });
  });

  describe('fetchGrievanceDocuments', () => {
    it('populates documents on fulfilled', () => {
      const store = createStore();
      const docs = [{ id: 'd1', document_type: 'evidence' }];
      store.dispatch({ type: fetchGrievanceDocuments.fulfilled.type, payload: docs });
      expect(store.getState().grievances.documents).toEqual(docs);
    });
  });

  describe('uploadGrievanceDocument', () => {
    it('prepends document on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievanceDocuments.fulfilled.type, payload: [{ id: 'd1' }] });
      store.dispatch({ type: uploadGrievanceDocument.fulfilled.type, payload: { id: 'd2' } });
      expect(store.getState().grievances.documents[0].id).toBe('d2');
    });
  });

  describe('deleteGrievanceDocument', () => {
    it('removes document on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievanceDocuments.fulfilled.type, payload: [{ id: 'd1' }, { id: 'd2' }] });
      store.dispatch({ type: deleteGrievanceDocument.fulfilled.type, payload: { document_id: 'd1', message: 'Deleted' } });
      expect(store.getState().grievances.documents).toHaveLength(1);
    });
  });

  describe('fetchGrievanceTimeline', () => {
    it('populates timeline on fulfilled', () => {
      const store = createStore();
      const timeline = [{ id: 't1', event: 'created' }];
      store.dispatch({ type: fetchGrievanceTimeline.fulfilled.type, payload: timeline });
      expect(store.getState().grievances.timeline).toEqual(timeline);
    });
  });

  describe('fetchGrievanceHearings', () => {
    it('populates hearings on fulfilled', () => {
      const store = createStore();
      const hearings = [{ id: 'h1', date: '2026-01-01' }];
      store.dispatch({ type: fetchGrievanceHearings.fulfilled.type, payload: hearings });
      expect(store.getState().grievances.hearings).toEqual(hearings);
    });
  });

  describe('createGrievanceHearing', () => {
    it('prepends hearing on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchGrievanceHearings.fulfilled.type, payload: [{ id: 'h1' }] });
      store.dispatch({ type: createGrievanceHearing.fulfilled.type, payload: { id: 'h2' } });
      expect(store.getState().grievances.hearings[0].id).toBe('h2');
    });
  });

  describe('fetchGrievanceStats', () => {
    it('populates stats on fulfilled', () => {
      const store = createStore();
      const stats = { total: 10, open: 5 };
      store.dispatch({ type: fetchGrievanceStats.fulfilled.type, payload: stats });
      expect(store.getState().grievances.stats).toEqual(stats);
    });
  });
});
