import { configureStore } from '@reduxjs/toolkit';
import { AuthSlice, login, register, logoutUser, refreshToken, setToken, clearState, setUserSubscription, setUserInfo } from '../AuthenticationSlice';

jest.mock('@/services/api/api', () => ({
  apiGet: jest.fn(),
  apiPost: jest.fn(),
  apiPut: jest.fn(),
  apiDelete: jest.fn(),
  axiosInstance: { post: jest.fn() },
  API_ENDPOINT: 'http://localhost',
}));

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

jest.mock('@/constants', () => ({
  DOMAIN_SUFFIX: '.ebitserp.com',
}));

const createStore = () => configureStore({ reducer: { auth: AuthSlice.reducer } });

describe('AuthenticationSlice', () => {
  it('has correct initial state', () => {
    const store = createStore();
    const state = store.getState().auth;
    expect(state.token).toBeNull();
    expect(state.error).toBeNull();
    expect(state.loading).toBe(false);
    expect(state.user).toBeNull();
    expect(state.provision_token).toBeNull();
    expect(state.provision_domain).toBeNull();
    expect(state.provisioning).toBe(false);
    expect(state.provision_steps_done).toBe(0);
    expect(state.provision_current_step).toBe('');
  });

  describe('reducers', () => {
    it('setToken sets the token', () => {
      const store = createStore();
      store.dispatch(setToken('abc-123'));
      expect(store.getState().auth.token).toBe('abc-123');
    });

    it('clearState resets auth fields', () => {
      const store = createStore();
      store.dispatch(setToken('abc'));
      store.dispatch(clearState());
      const state = store.getState().auth;
      expect(state.token).toBeNull();
      expect(state.user).toBeNull();
      expect(state.error).toBeNull();
      expect(state.provisioning).toBe(false);
    });

    it('setUserSubscription updates user subscription', () => {
      const store = createStore();
      const user = { user_id: '1', name: 'Test', email: 'test@test.com' } as any;
      store.dispatch(setUserInfo(user));
      store.dispatch(setUserSubscription({ plan: 'pro' } as any));
      expect(store.getState().auth.user?.subscription).toEqual({ plan: 'pro' });
    });

    it('setUserInfo sets user object', () => {
      const store = createStore();
      const user = { user_id: '1', name: 'Test' } as any;
      store.dispatch(setUserInfo(user));
      expect(store.getState().auth.user).toEqual(user);
    });
  });

  describe('login thunk', () => {
    it('sets loading on pending', () => {
      const store = createStore();
      store.dispatch({ type: login.pending.type });
      expect(store.getState().auth.loading).toBe(true);
      expect(store.getState().auth.error).toBeNull();
    });

    it('sets token and user on fulfilled', () => {
      const store = createStore();
      const payload = { access_token: 'tok-123', user: { user_id: '1', name: 'Test' } };
      store.dispatch({ type: login.fulfilled.type, payload });
      const state = store.getState().auth;
      expect(state.loading).toBe(false);
      expect(state.token).toBe('tok-123');
      expect(state.user).toEqual(payload.user);
    });

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

  describe('register thunk', () => {
    it('sets provisioning state on fulfilled', () => {
      const store = createStore();
      const payload = { provision_token: 'pt-1', domain: 'test.ebitserp.com' };
      store.dispatch({ type: register.fulfilled.type, payload });
      const state = store.getState().auth;
      expect(state.provision_token).toBe('pt-1');
      expect(state.provision_domain).toBe('test.ebitserp.com');
      expect(state.provisioning).toBe(true);
      expect(state.loading).toBe(false);
    });

    it('clears provisioning on rejected', () => {
      const store = createStore();
      store.dispatch({ type: register.rejected.type, error: { message: 'fail' } });
      const state = store.getState().auth;
      expect(state.provisioning).toBe(false);
      expect(state.provision_token).toBeNull();
    });
  });

  describe('refreshToken thunk', () => {
    it('updates token and user on fulfilled', () => {
      const store = createStore();
      const payload = { access_token: 'new-tok', user: { user_id: '2' } };
      store.dispatch({ type: refreshToken.fulfilled.type, payload });
      expect(store.getState().auth.token).toBe('new-tok');
    });

    it('clears auth on rejected', () => {
      const store = createStore();
      store.dispatch(setToken('old'));
      store.dispatch({ type: refreshToken.rejected.type });
      expect(store.getState().auth.token).toBeNull();
      expect(store.getState().auth.user).toBeNull();
    });
  });

  describe('logoutUser thunk', () => {
    it('clears state on fulfilled', () => {
      const store = createStore();
      store.dispatch(setToken('tok'));
      store.dispatch({ type: logoutUser.fulfilled.type });
      const state = store.getState().auth;
      expect(state.token).toBeNull();
      expect(state.user).toBeNull();
      expect(state.error).toBeNull();
    });
  });
});
