import { configureStore } from '@reduxjs/toolkit';
import { UserSlice, fetchUsers, fetchAuthUser, fetchRoles, fetchPermissions, deleteUser, createRole, deleteRole, fetchUserDetails, updateUser } from '../UserSlice';

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') },
}));

jest.mock('@/constants', () => ({
  LOCAL_STORAGE: { USER: 'user', EMPLOYEE: 'employee', AUTH_USER: 'auth_user', AUTH_EMPLOYEE: 'auth_employee' },
}));

jest.mock('../../authentication/AuthenticationSlice', () => ({
  setUserInfo: jest.fn((payload) => ({ type: 'auth/setUserInfo', payload })),
}));

const createStore = () => configureStore({ reducer: { user: UserSlice.reducer } });

describe('UserSlice', () => {
  it('has correct initial state', () => {
    const store = createStore();
    const state = store.getState().user;
    expect(state.loading).toBe(false);
    expect(state.error).toBeNull();
    expect(state.users).toEqual([]);
    expect(state.user).toBeNull();
    expect(state.employee).toBeNull();
    expect(state.roles).toEqual([]);
    expect(state.permissions).toEqual([]);
    expect(state.rolePermissions).toEqual([]);
    expect(state.permissionRoles).toEqual([]);
    expect(state.wallet).toBeNull();
  });

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

    it('populates users on fulfilled', () => {
      const store = createStore();
      const users = [{ user_id: '1', name: 'A' }, { user_id: '2', name: 'B' }];
      store.dispatch({ type: fetchUsers.fulfilled.type, payload: users });
      expect(store.getState().user.users).toEqual(users);
      expect(store.getState().user.loading).toBe(false);
    });

    it('sets loading false on rejected', () => {
      const store = createStore();
      store.dispatch({ type: fetchUsers.pending.type });
      store.dispatch({ type: fetchUsers.rejected.type });
      expect(store.getState().user.loading).toBe(false);
    });
  });

  describe('fetchAuthUser', () => {
    it('sets user and employee on fulfilled', () => {
      const store = createStore();
      const user = { user_id: '1', name: 'Test', employee: { employee_id: 'e1' } };
      store.dispatch({ type: fetchAuthUser.fulfilled.type, payload: user });
      expect(store.getState().user.user).toEqual(user);
      expect(store.getState().user.employee).toEqual({ employee_id: 'e1' });
    });
  });

  describe('fetchUserDetails', () => {
    it('sets user on fulfilled', () => {
      const store = createStore();
      const user = { user_id: '1', name: 'Detail' };
      store.dispatch({ type: fetchUserDetails.fulfilled.type, payload: user });
      expect(store.getState().user.user).toEqual(user);
      expect(store.getState().user.loading).toBe(false);
    });
  });

  describe('deleteUser', () => {
    it('removes user from list on fulfilled', () => {
      const store = createStore();
      const users = [{ user_id: '1' }, { user_id: '2' }];
      store.dispatch({ type: fetchUsers.fulfilled.type, payload: users });
      store.dispatch({ type: deleteUser.fulfilled.type, payload: { user_id: '1', message: 'Deleted' } });
      expect(store.getState().user.users).toHaveLength(1);
      expect(store.getState().user.users[0].user_id).toBe('2');
    });
  });

  describe('fetchRoles', () => {
    it('populates roles on fulfilled', () => {
      const store = createStore();
      const roles = [{ uuid: 'r1', name: 'Admin' }];
      store.dispatch({ type: fetchRoles.fulfilled.type, payload: roles });
      expect(store.getState().user.roles).toEqual(roles);
      expect(store.getState().user.loading).toBe(false);
    });
  });

  describe('createRole', () => {
    it('prepends role on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchRoles.fulfilled.type, payload: [{ uuid: 'r1' }] });
      store.dispatch({ type: createRole.fulfilled.type, payload: { uuid: 'r2', name: 'New' } });
      expect(store.getState().user.roles[0].uuid).toBe('r2');
    });
  });

  describe('deleteRole', () => {
    it('removes role from list on fulfilled', () => {
      const store = createStore();
      store.dispatch({ type: fetchRoles.fulfilled.type, payload: [{ uuid: 'r1' }, { uuid: 'r2' }] });
      store.dispatch({ type: deleteRole.fulfilled.type, payload: { uuid: 'r1', message: 'Deleted' } });
      expect(store.getState().user.roles).toHaveLength(1);
    });
  });

  describe('fetchPermissions', () => {
    it('populates permissions on fulfilled', () => {
      const store = createStore();
      const perms = [{ uuid: 'p1', name: 'view' }];
      store.dispatch({ type: fetchPermissions.fulfilled.type, payload: perms });
      expect(store.getState().user.permissions).toEqual(perms);
    });
  });

  describe('updateUser', () => {
    it('updates user on fulfilled', () => {
      const store = createStore();
      const user = { user_id: '1', name: 'Updated' };
      store.dispatch({ type: updateUser.fulfilled.type, payload: user });
      expect(store.getState().user.user).toEqual(user);
      expect(store.getState().user.loading).toBe(false);
    });
  });
});
