import 'reflect-metadata';

import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { DataSource } from 'typeorm';

import { PageView } from '@core/analytics/domain/entities/PageView';

import { PageViewOrmEntity } from '@adapters/analytics/persistence/typeorm/entities/PageViewOrmEntity';
import { EngagementEventOrmEntity } from '@adapters/analytics/persistence/typeorm/entities/EngagementEventOrmEntity';
import { AnalyticsSnapshotOrmEntity } from '@adapters/analytics/persistence/typeorm/entities/AnalyticsSnapshotOrmEntity';

import { PageViewOrmMapper } from '@adapters/analytics/persistence/typeorm/mappers/PageViewOrmMapper';
import { EngagementEventOrmMapper } from '@adapters/analytics/persistence/typeorm/mappers/EngagementEventOrmMapper';
import { AnalyticsSnapshotOrmMapper } from '@adapters/analytics/persistence/typeorm/mappers/AnalyticsSnapshotOrmMapper';

import { TypeOrmPageViewRepository } from '@adapters/analytics/persistence/typeorm/repositories/TypeOrmPageViewRepository';
import { TypeOrmEngagementRepository } from '@adapters/analytics/persistence/typeorm/repositories/TypeOrmEngagementRepository';
import { TypeOrmAnalyticsSnapshotRepository } from '@adapters/analytics/persistence/typeorm/repositories/TypeOrmAnalyticsSnapshotRepository';

const databaseUrl = process.env.DATABASE_URL;
const describeIfDatabase = databaseUrl ? describe : describe.skip;

describeIfDatabase('TypeORM Analytics repositories (postgres slice)', () => {
  let dataSource: DataSource;

  beforeAll(async () => {
    if (!databaseUrl) {
      throw new Error('DATABASE_URL is required to run postgres integration tests');
    }

    dataSource = new DataSource({
      type: 'postgres',
      url: databaseUrl,
      entities: [PageViewOrmEntity, EngagementEventOrmEntity, AnalyticsSnapshotOrmEntity],
      synchronize: true,
    });

    await dataSource.initialize();
  });

  afterAll(async () => {
    if (dataSource?.isInitialized) {
      await dataSource.destroy();
    }
  });

  it('supports: persist page view + read it back + count unique visitors', async () => {
    const pageViewOrmRepo = dataSource.getRepository(PageViewOrmEntity);
    const engagementOrmRepo = dataSource.getRepository(EngagementEventOrmEntity);
    const snapshotOrmRepo = dataSource.getRepository(AnalyticsSnapshotOrmEntity);

    await snapshotOrmRepo.clear();
    await engagementOrmRepo.clear();
    await pageViewOrmRepo.clear();

    const pageViewRepo = new TypeOrmPageViewRepository(pageViewOrmRepo, new PageViewOrmMapper());
    const engagementRepo = new TypeOrmEngagementRepository(engagementOrmRepo, new EngagementEventOrmMapper());
    const snapshotRepo = new TypeOrmAnalyticsSnapshotRepository(snapshotOrmRepo, new AnalyticsSnapshotOrmMapper());

    // Ensure all repositories at least construct and basic ops work
    expect(pageViewRepo).toBeDefined();
    expect(engagementRepo).toBeDefined();
    expect(snapshotRepo).toBeDefined();

    const pv1 = PageView.create({
      id: `pv-it-${Date.now()}`,
      entityType: 'league',
      entityId: 'league-it-1',
      visitorType: 'anonymous',
      sessionId: 'sess-it-1',
      visitorId: 'visitor-it-1',
      timestamp: new Date(),
      durationMs: 8000,
    });

    await pageViewRepo.save(pv1);

    const loaded = await pageViewRepo.findById(pv1.id);
    expect(loaded?.id).toBe(pv1.id);

    const unique = await pageViewRepo.countUniqueVisitors('league', 'league-it-1');
    expect(unique).toBe(1);
  });
});