import type { Repository } from 'typeorm';
import { describe, expect, it, vi } from 'vitest';

import type { FeedItem } from '@core/social/domain/types/FeedItem';

import { FeedItemOrmEntity } from '../entities/FeedItemOrmEntity';
import { FriendshipOrmEntity } from '../entities/FriendshipOrmEntity';
import { FeedItemOrmMapper } from '../mappers/FeedItemOrmMapper';
import { TypeOrmFeedRepository } from './TypeOrmFeedRepository';

describe('TypeOrmFeedRepository', () => {
  it('getFeedForDriver returns mapped items for friend actor ids', async () => {
    const feedRepo = {
      find: vi.fn(),
    } as unknown as Repository<FeedItemOrmEntity>;

    const friendshipRepo = {
      find: vi.fn(),
    } as unknown as Repository<FriendshipOrmEntity>;

    const mapper = {
      toDomain: vi.fn(),
    } as unknown as FeedItemOrmMapper;

    const repo = new TypeOrmFeedRepository(feedRepo, friendshipRepo, mapper);

    const friendship = new FriendshipOrmEntity();
    friendship.driverId = '00000000-0000-0000-0000-000000000001';
    friendship.friendId = '00000000-0000-0000-0000-000000000002';
    friendship.createdAt = null;

    friendshipRepo.find = vi.fn().mockResolvedValue([friendship]);

    const ormItem = new FeedItemOrmEntity();
    ormItem.id = '00000000-0000-0000-0000-0000000000aa';
    ormItem.timestamp = new Date('2025-01-01T00:00:00.000Z');
    ormItem.type = 'new-result-posted';
    ormItem.actorFriendId = null;
    ormItem.actorDriverId = friendship.friendId;
    ormItem.leagueId = null;
    ormItem.raceId = null;
    ormItem.teamId = null;
    ormItem.position = null;
    ormItem.headline = 'Headline';
    ormItem.body = null;
    ormItem.ctaLabel = null;
    ormItem.ctaHref = null;

    feedRepo.find = vi.fn().mockResolvedValue([ormItem]);

    const mapped: FeedItem = {
      id: ormItem.id,
      timestamp: ormItem.timestamp,
      type: ormItem.type,
      actorDriverId: ormItem.actorDriverId ?? undefined,
      headline: ormItem.headline,
    };

    mapper.toDomain = vi.fn().mockReturnValue(mapped);

    const result = await repo.getFeedForDriver(friendship.driverId);

    expect(friendshipRepo.find).toHaveBeenCalledWith({ where: { driverId: friendship.driverId } });
    expect(feedRepo.find).toHaveBeenCalledTimes(1);
    expect(mapper.toDomain).toHaveBeenCalledWith(ormItem);
    expect(result).toEqual([mapped]);
  });

  it('getFeedForDriver returns [] when driver has no friends', async () => {
    const feedRepo = {
      find: vi.fn(),
    } as unknown as Repository<FeedItemOrmEntity>;

    const friendshipRepo = {
      find: vi.fn().mockResolvedValue([]),
    } as unknown as Repository<FriendshipOrmEntity>;

    const mapper = {
      toDomain: vi.fn(),
    } as unknown as FeedItemOrmMapper;

    const repo = new TypeOrmFeedRepository(feedRepo, friendshipRepo, mapper);

    const result = await repo.getFeedForDriver('00000000-0000-0000-0000-000000000001');

    expect(result).toEqual([]);
    expect(feedRepo.find).not.toHaveBeenCalled();
    expect(mapper.toDomain).not.toHaveBeenCalled();
  });
});