import { describe, it, expect, vi, beforeEach } from 'vitest';
import { DataSource, ObjectLiteral } from 'typeorm';
import { ConcreteCrudService } from '../../src/services/concrete-crud.service';
import { AppDataSource, initializeDataSource } from '@d8d/shared-utils';

// 测试实体类
class TestEntity implements ObjectLiteral {
  id!: number;
  name!: string;
}

describe('ConcreteCrudService', () => {
  let mockDataSource: DataSource;
  let concreteService: ConcreteCrudService<TestEntity>;

  beforeEach(() => {
    mockDataSource = {
      getRepository: vi.fn().mockReturnValue({
        createQueryBuilder: vi.fn().mockReturnValue({
          leftJoinAndSelect: vi.fn().mockReturnThis(),
          andWhere: vi.fn().mockReturnThis(),
          orderBy: vi.fn().mockReturnThis(),
          skip: vi.fn().mockReturnThis(),
          take: vi.fn().mockReturnThis(),
          getManyAndCount: vi.fn().mockResolvedValue([[], 0])
        }),
        findOne: vi.fn().mockResolvedValue(null),
        create: vi.fn().mockImplementation((data) => ({ ...data, id: 1 })),
        save: vi.fn().mockImplementation((entity) => Promise.resolve(entity)),
        update: vi.fn().mockResolvedValue({ affected: 1 }),
        delete: vi.fn().mockResolvedValue({ affected: 1 })
      })
    } as any;

    // 在测试环境中初始化 AppDataSource
    initializeDataSource([TestEntity]);
    // 模拟 AppDataSource 的 getRepository 方法
    vi.spyOn(AppDataSource, 'getRepository').mockImplementation(mockDataSource.getRepository);

    concreteService = new ConcreteCrudService(TestEntity);
  });

  describe('构造函数', () => {
    it('应该正确初始化父类', () => {
      expect(concreteService).toBeDefined();
      expect(mockDataSource.getRepository).toHaveBeenCalledWith(TestEntity);
    });

    it('应该支持用户跟踪选项', () => {
      const serviceWithTracking = new ConcreteCrudService(
        TestEntity,
        { userTracking: { createdByField: 'creator' } }
      );

      expect(serviceWithTracking).toBeDefined();
    });

    it('应该支持关联字段选项', () => {
      const serviceWithRelations = new ConcreteCrudService(
        TestEntity,
        { relationFields: { relatedIds: { relationName: 'related', targetEntity: TestEntity } } }
      );

      expect(serviceWithRelations).toBeDefined();
    });
  });

  describe('继承的方法', () => {
    it('应该能够调用 getList 方法', async () => {
      const [data, total] = await concreteService.getList(1, 10);

      expect(data).toEqual([]);
      expect(total).toBe(0);
    });

    it('应该能够调用 getById 方法', async () => {
      const result = await concreteService.getById(1);

      expect(result).toBeNull();
    });

    it('应该能够调用 create 方法', async () => {
      const createData = { name: 'Test Entity' };
      const result = await concreteService.create(createData);

      expect(result).toBeDefined();
      expect(result.id).toBe(1);
    });

    it('应该能够调用 update 方法', async () => {
      const updateData = { name: 'Updated Entity' };
      const result = await concreteService.update(1, updateData);

      expect(result).toBeNull(); // 因为模拟的 findOne 返回 null
    });

    it('应该能够调用 delete 方法', async () => {
      const result = await concreteService.delete(1);

      expect(result).toBe(true);
    });
  });
});