import '@angular/compiler';
import {
  describe,
  it,
  expect,
  vi
} from 'vitest';
import {
  Injector,
  runInInjectionContext,
  signal
} from '@angular/core';
import { Store } from '@ngrx/store';
import { of } from 'rxjs';

import { FindServersComponent } from './find-servers.component';
import { selectSavedRooms } from '../../../../store/rooms/rooms.selectors';
import { ServerDirectoryFacade } from '../../application/facades/server-directory.facade';
import { initializeAppI18nForTests, provideAppI18nForTests } from '../../../../core/i18n/app-i18n.testing';
import type { ServerInfo } from '../../domain/models/server-directory.model';
import type { Room } from '../../../../shared-kernel';

function makeServer(id: string): ServerInfo {
  return { id, name: id, maxUsers: 50, userCount: 1, isPrivate: false } as unknown as ServerInfo;
}

function makeRoom(id: string): Room {
  return { id, name: id } as unknown as Room;
}

interface HarnessOptions {
  saved?: Room[];
  featured?: ServerInfo[];
  trending?: ServerInfo[];
}

function createHarness(options: HarnessOptions = {}) {
  const savedSig = signal<Room[]>(options.saved ?? []);
  const store = {
    selectSignal: (selector: unknown) => (selector === selectSavedRooms ? savedSig : signal(null)),
    dispatch: vi.fn()
  } as unknown as Store;
  const serverDirectory = {
    getFeaturedServers: vi.fn(() => of(options.featured ?? [])),
    getTrendingServers: vi.fn(() => of(options.trending ?? []))
  } as unknown as ServerDirectoryFacade;
  const injector = Injector.create({
    providers: [
      FindServersComponent,
      { provide: Store, useValue: store },
      { provide: ServerDirectoryFacade, useValue: serverDirectory },
      ...provideAppI18nForTests()
    ]
  });

  initializeAppI18nForTests(injector);
  const component = runInInjectionContext(injector, () => injector.get(FindServersComponent));

  return { component, savedSig };
}

describe('FindServersComponent', () => {
  it('builds featured and trending sections after init', () => {
    const { component } = createHarness({
      featured: [makeServer('f1')],
      trending: [makeServer('t1')]
    });

    component.ngOnInit();

    const ids = component.discoverySections().map((section) => section.id);

    expect(ids).toContain('featured');
    expect(ids).toContain('trending');
  });

  it('includes a recently-active section from saved rooms', () => {
    const { component } = createHarness({ saved: [makeRoom('r1')] });
    const recent = component.discoverySections().find((section) => section.id === 'recent');

    expect(recent).toBeTruthy();
    expect(recent?.servers[0].id).toBe('r1');
  });

  it('reports a new user when there is nothing to recommend', () => {
    const { component } = createHarness();

    component.ngOnInit();

    expect(component.isNewUser()).toBe(true);
    expect(component.discoverySections()).toHaveLength(0);
  });

  it('is not a new user once recommendations exist', () => {
    const { component } = createHarness({ featured: [makeServer('f1')] });

    component.ngOnInit();

    expect(component.isNewUser()).toBe(false);
  });
});
