import { Test, TestingModule } from '@nestjs/testing';
import { ConfigModule } from '@nestjs/config';
import { PrismaService } from '../../src/infrastructure/persistence/prisma/prisma.service';
import { ReportSnapshotRepository } from '../../src/infrastructure/persistence/repositories/report-snapshot.repository.impl';
import { ReportSnapshot } from '../../src/domain/aggregates/report-snapshot';
import {
  ReportType,
  ReportPeriod,
  SnapshotData,
  DataSource,
} from '../../src/domain/value-objects';

describe('ReportSnapshotRepository Integration', () => {
  let module: TestingModule;
  let repository: ReportSnapshotRepository;
  let prisma: PrismaService;

  beforeAll(async () => {
    module = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath: ['.env.test', '.env'],
        }),
      ],
      providers: [PrismaService, ReportSnapshotRepository],
    }).compile();

    repository = module.get<ReportSnapshotRepository>(ReportSnapshotRepository);
    prisma = module.get<PrismaService>(PrismaService);
  });

  afterAll(async () => {
    await prisma.$disconnect();
    await module.close();
  });

  beforeEach(async () => {
    // Clean up test data
    await prisma.reportSnapshot.deleteMany({
      where: { reportCode: { startsWith: 'TEST_' } },
    });
  });

  describe('save', () => {
    it('should create a new report snapshot', async () => {
      const snapshotData = SnapshotData.create({
        rows: [
          { rank: 1, userId: 1, score: 100 },
          { rank: 2, userId: 2, score: 90 },
        ],
        summary: { totalEntries: 2 },
      });

      const dataSource = DataSource.create(['test-service']);

      const snapshot = ReportSnapshot.create({
        reportType: ReportType.LEADERBOARD_REPORT,
        reportCode: 'TEST_SNAP_001',
        reportPeriod: ReportPeriod.DAILY,
        periodKey: '2024-01-15',
        snapshotData,
        dataSource,
        periodStartAt: new Date('2024-01-15'),
        periodEndAt: new Date('2024-01-15'),
      });

      const saved = await repository.save(snapshot);

      expect(saved.id).toBeDefined();
      expect(saved.reportCode).toBe('TEST_SNAP_001');
      expect(saved.rowCount).toBe(2);
    });
  });

  describe('findByCodeAndPeriodKey', () => {
    it('should find snapshot by code and period key', async () => {
      const snapshotData = SnapshotData.create({
        rows: [{ data: 'test' }],
      });

      const snapshot = ReportSnapshot.create({
        reportType: ReportType.PLANTING_REPORT,
        reportCode: 'TEST_SNAP_002',
        reportPeriod: ReportPeriod.MONTHLY,
        periodKey: '2024-01',
        snapshotData,
        dataSource: DataSource.create(['test']),
        periodStartAt: new Date('2024-01-01'),
        periodEndAt: new Date('2024-01-31'),
      });

      await repository.save(snapshot);

      const found = await repository.findByCodeAndPeriodKey('TEST_SNAP_002', '2024-01');

      expect(found).not.toBeNull();
      expect(found?.reportPeriod).toBe(ReportPeriod.MONTHLY);
    });
  });

  describe('findLatestByCode', () => {
    it('should find the latest snapshot by code', async () => {
      // Create older snapshot
      const older = ReportSnapshot.create({
        reportType: ReportType.PLANTING_REPORT,
        reportCode: 'TEST_SNAP_003',
        reportPeriod: ReportPeriod.DAILY,
        periodKey: '2024-01-14',
        snapshotData: SnapshotData.create({ rows: [] }),
        dataSource: DataSource.create(['test']),
        periodStartAt: new Date('2024-01-14'),
        periodEndAt: new Date('2024-01-14'),
      });
      await repository.save(older);

      // Create newer snapshot
      const newer = ReportSnapshot.create({
        reportType: ReportType.PLANTING_REPORT,
        reportCode: 'TEST_SNAP_003',
        reportPeriod: ReportPeriod.DAILY,
        periodKey: '2024-01-15',
        snapshotData: SnapshotData.create({ rows: [{ latest: true }] }),
        dataSource: DataSource.create(['test']),
        periodStartAt: new Date('2024-01-15'),
        periodEndAt: new Date('2024-01-15'),
      });
      await repository.save(newer);

      const latest = await repository.findLatestByCode('TEST_SNAP_003');

      expect(latest).not.toBeNull();
      expect(latest?.periodKey).toBe('2024-01-15');
    });
  });

  describe('findByPeriod', () => {
    it('should find snapshots by period type', async () => {
      // Create daily snapshot
      const daily = ReportSnapshot.create({
        reportType: ReportType.PLANTING_REPORT,
        reportCode: 'TEST_SNAP_004',
        reportPeriod: ReportPeriod.DAILY,
        periodKey: '2024-01-15',
        snapshotData: SnapshotData.create({ rows: [] }),
        dataSource: DataSource.create(['test']),
        periodStartAt: new Date('2024-01-15'),
        periodEndAt: new Date('2024-01-15'),
      });
      await repository.save(daily);

      // Create monthly snapshot
      const monthly = ReportSnapshot.create({
        reportType: ReportType.PLANTING_REPORT,
        reportCode: 'TEST_SNAP_005',
        reportPeriod: ReportPeriod.MONTHLY,
        periodKey: '2024-01',
        snapshotData: SnapshotData.create({ rows: [] }),
        dataSource: DataSource.create(['test']),
        periodStartAt: new Date('2024-01-01'),
        periodEndAt: new Date('2024-01-31'),
      });
      await repository.save(monthly);

      const dailySnapshots = await repository.findByPeriod(ReportPeriod.DAILY);
      const testDailySnapshots = dailySnapshots.filter(s => s.reportCode.startsWith('TEST_'));

      expect(testDailySnapshots.length).toBe(1);
      expect(testDailySnapshots[0].reportCode).toBe('TEST_SNAP_004');
    });
  });
});
