import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { NotificationsApi } from './notifications-api';
import { NotificationsStore } from './notifications-store';

describe('NotificationsStore', () => {
  let api: {
    loadUnreadCount: ReturnType<typeof vi.fn>;
    loadNotifications: ReturnType<typeof vi.fn>;
    markRead: ReturnType<typeof vi.fn>;
    markAllRead: ReturnType<typeof vi.fn>;
  };
  let store: NotificationsStore;

  beforeEach(() => {
    api = {
      loadUnreadCount: vi.fn().mockReturnValue(of({ count: 0 })),
      loadNotifications: vi.fn().mockReturnValue(of({ data: [], page: 1, limit: 20, total: 0, hasNextPage: false })),
      markRead: vi.fn().mockReturnValue(of(undefined)),
      markAllRead: vi.fn().mockReturnValue(of(undefined)),
    };
    TestBed.configureTestingModule({ providers: [{ provide: NotificationsApi, useValue: api }] });
    store = TestBed.inject(NotificationsStore);
  });

  it('polls the unread count immediately when polling starts for a team', () => {
    api.loadUnreadCount.mockReturnValue(of({ count: 4 }));

    store.startPolling(10);

    expect(api.loadUnreadCount).toHaveBeenCalledWith(10);
    expect(store.unreadCount()).toBe(4);
  });

  it('does not start a second poll loop for the same team id', () => {
    store.startPolling(10);
    store.startPolling(10);

    expect(api.loadUnreadCount).toHaveBeenCalledTimes(1);
  });

  it('switches polling to a newly routed team', () => {
    store.startPolling(10);
    api.loadUnreadCount.mockReturnValue(of({ count: 7 }));

    store.startPolling(11);

    expect(api.loadUnreadCount).toHaveBeenCalledWith(11);
    expect(store.unreadCount()).toBe(7);
  });

  it('loads the recent notification list', () => {
    const data = [
      {
        id: 1,
        event: 'player_creation' as const,
        actorUserId: 9,
        payload: { playerId: 21, playerName: 'Ada Lovelace' },
        read: false,
        createdAt: '2026-08-04T10:00:00.000Z',
      },
    ];
    api.loadNotifications.mockReturnValue(of({ data, page: 1, limit: 20, total: 1, hasNextPage: false }));

    store.loadRecent(10);

    expect(api.loadNotifications).toHaveBeenCalledWith(10, { page: 1, limit: 20 });
    expect(store.notifications()).toEqual(data);
  });

  it('marks a notification as read locally and decrements the unread count', () => {
    api.loadUnreadCount.mockReturnValue(of({ count: 3 }));
    store.startPolling(10);
    const data = [
      { id: 1, event: 'player_creation' as const, actorUserId: 9, payload: {}, read: false, createdAt: 'x' },
    ];
    api.loadNotifications.mockReturnValue(of({ data, page: 1, limit: 20, total: 1, hasNextPage: false }));
    store.loadRecent(10);

    store.markRead(10, 1);

    expect(api.markRead).toHaveBeenCalledWith(10, 1);
    expect(store.notifications()[0].read).toBe(true);
    expect(store.unreadCount()).toBe(2);
  });

  it('marks all notifications as read locally and zeroes the unread count', () => {
    api.loadUnreadCount.mockReturnValue(of({ count: 5 }));
    store.startPolling(10);
    const data = [
      { id: 1, event: 'player_creation' as const, actorUserId: 9, payload: {}, read: false, createdAt: 'x' },
    ];
    api.loadNotifications.mockReturnValue(of({ data, page: 1, limit: 20, total: 1, hasNextPage: false }));
    store.loadRecent(10);

    store.markAllRead(10);

    expect(api.markAllRead).toHaveBeenCalledWith(10);
    expect(store.notifications()[0].read).toBe(true);
    expect(store.unreadCount()).toBe(0);
  });
});
