import { Module } from '@nestjs/common';
import { TypeOrmModule, getDataSourceToken } from '@nestjs/typeorm';
import type { DataSource } from 'typeorm';

import { LoggingModule } from '../../domain/logging/LoggingModule';
import {
    ANALYTICS_ENGAGEMENT_REPOSITORY_TOKEN,
    ANALYTICS_PAGE_VIEW_REPOSITORY_TOKEN,
    ANALYTICS_SNAPSHOT_REPOSITORY_TOKEN,
} from '../analytics/AnalyticsPersistenceTokens';

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

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

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

const typeOrmFeatureImports = [
  TypeOrmModule.forFeature([PageViewOrmEntity, EngagementEventOrmEntity, AnalyticsSnapshotOrmEntity]),
];

@Module({
  imports: [LoggingModule, ...typeOrmFeatureImports],
  providers: [
    { provide: PageViewOrmMapper, useFactory: () => new PageViewOrmMapper() },
    { provide: EngagementEventOrmMapper, useFactory: () => new EngagementEventOrmMapper() },
    { provide: AnalyticsSnapshotOrmMapper, useFactory: () => new AnalyticsSnapshotOrmMapper() },

    {
      provide: ANALYTICS_PAGE_VIEW_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: PageViewOrmMapper) =>
        new TypeOrmPageViewRepository(dataSource.getRepository(PageViewOrmEntity), mapper),
      inject: [getDataSourceToken(), PageViewOrmMapper],
    },
    {
      provide: ANALYTICS_ENGAGEMENT_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: EngagementEventOrmMapper) =>
        new TypeOrmEngagementRepository(dataSource.getRepository(EngagementEventOrmEntity), mapper),
      inject: [getDataSourceToken(), EngagementEventOrmMapper],
    },
    {
      provide: ANALYTICS_SNAPSHOT_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: AnalyticsSnapshotOrmMapper) =>
        new TypeOrmAnalyticsSnapshotRepository(dataSource.getRepository(AnalyticsSnapshotOrmEntity), mapper),
      inject: [getDataSourceToken(), AnalyticsSnapshotOrmMapper],
    },
  ],
  exports: [ANALYTICS_PAGE_VIEW_REPOSITORY_TOKEN, ANALYTICS_ENGAGEMENT_REPOSITORY_TOKEN, ANALYTICS_SNAPSHOT_REPOSITORY_TOKEN],
})
export class PostgresAnalyticsPersistenceModule {}