import { EngagementEvent, type EngagementAction, type EngagementEntityType } from '@core/analytics/domain/entities/EngagementEvent';

describe('EngagementEvent', () => {
  const baseProps = (): Parameters<typeof EngagementEvent.create>[0] => ({
    id: 'event-1',
    action: 'click_sponsor_logo',
    entityType: 'league',
    entityId: 'entity_123',
    actorType: 'anonymous',
    sessionId: 'session-1',
    metadata: { source: 'test', count: 1, ok: true },
  });

  it('creates an event with trimmed entityId', () => {
    const event = EngagementEvent.create({
      id: 'event-1',
      action: 'view_schedule',
      entityType: 'league',
      entityId: '   entity_456   ',
      actorType: 'driver',
      actorId: 'driver-1',
      sessionId: 'session-1',
    });

    expect(event.entityId).toBe('entity_456');
  });

  it('throws if id is missing', () => {
    expect(() => EngagementEvent.create({ ...baseProps(), id: '' })).toThrow(Error);
    expect(() => EngagementEvent.create({ ...baseProps(), id: '   ' })).toThrow(Error);
  });

  it('throws if action is missing', () => {
    expect(() =>
      EngagementEvent.create({ ...baseProps(), action: undefined } as unknown as Parameters<
        typeof EngagementEvent.create
      >[0]),
    ).toThrow(Error);
  });

  it('throws if entityType is missing', () => {
    expect(() =>
      EngagementEvent.create({ ...baseProps(), entityType: undefined as unknown as EngagementEntityType }),
    ).toThrow(Error);
  });

  it('throws if entityId is missing', () => {
    expect(() => EngagementEvent.create({ ...baseProps(), entityId: '' })).toThrow(Error);
    expect(() => EngagementEvent.create({ ...baseProps(), entityId: '   ' })).toThrow(Error);
  });

  it('throws if sessionId is missing', () => {
    expect(() => EngagementEvent.create({ ...baseProps(), sessionId: '' })).toThrow(Error);
    expect(() => EngagementEvent.create({ ...baseProps(), sessionId: '   ' })).toThrow(Error);
  });

  it('detects sponsor engagement', () => {
    expect(EngagementEvent.create(baseProps()).isSponsorEngagement()).toBe(true);

    const sponsorEntity = EngagementEvent.create({
      id: 'event-2',
      action: 'view_schedule',
      entityType: 'sponsor',
      entityId: 'sponsor-1',
      actorType: 'anonymous',
      sessionId: 'session-2',
    });
    expect(sponsorEntity.isSponsorEngagement()).toBe(true);

    const nonSponsor = EngagementEvent.create({
      id: 'event-3',
      action: 'view_standings',
      entityType: 'league',
      entityId: 'league-1',
      actorType: 'anonymous',
      sessionId: 'session-3',
    });
    expect(nonSponsor.isSponsorEngagement()).toBe(false);
  });

  it('detects conversion events', () => {
    const join = EngagementEvent.create({
      id: 'event-4',
      action: 'join_league',
      entityType: 'league',
      entityId: 'league-1',
      actorType: 'driver',
      actorId: 'driver-1',
      sessionId: 'session-4',
    });
    expect(join.isConversionEvent()).toBe(true);

    const view = EngagementEvent.create({
      id: 'event-5',
      action: 'view_schedule',
      entityType: 'league',
      entityId: 'league-1',
      actorType: 'anonymous',
      sessionId: 'session-5',
    });
    expect(view.isConversionEvent()).toBe(false);
  });

  it('returns configured engagement weights', () => {
    const weights: Array<{ action: EngagementAction; expected: number }> = [
      { action: 'click_sponsor_logo', expected: 2 },
      { action: 'click_sponsor_url', expected: 5 },
      { action: 'download_livery_pack', expected: 3 },
      { action: 'join_league', expected: 10 },
      { action: 'register_race', expected: 8 },
      { action: 'view_standings', expected: 1 },
      { action: 'view_schedule', expected: 1 },
      { action: 'share_social', expected: 4 },
      { action: 'contact_sponsor', expected: 15 },
    ];

    for (const { action, expected } of weights) {
      const event = EngagementEvent.create({
        id: `event-${action}`,
        action,
        entityType: 'league',
        entityId: 'league-1',
        actorType: 'anonymous',
        sessionId: 'session-1',
      });
      expect(event.getEngagementWeight()).toBe(expected);
    }
  });
});