import { Router } from 'express';
import { DataSource } from 'typeorm';
import {
  ReportsService,
  ReportExecutionService,
  ReportSchedulerService,
  DashboardsService,
  LegacyReportsService,
} from './services';
import { ReportsController, DashboardsController, LegacyReportsController } from './controllers';
import {
  ReportDefinition,
  ReportExecution,
  ReportSchedule,
  ReportRecipient,
  ScheduleExecution,
  Dashboard,
  DashboardWidget,
  WidgetQuery,
  CustomReport,
  DataModelEntity,
  DataModelField,
  DataModelRelationship,
} from './entities';

/**
 * Options for configuring the Reports module
 */
export interface ReportsModuleOptions {
  dataSource: DataSource;
  basePath?: string;
}

/**
 * ReportsModule
 *
 * Complete reports and dashboards management module.
 *
 * Features:
 * - Report definitions (templates)
 * - Report executions (history and results)
 * - Scheduled reports with delivery
 * - Custom user reports
 * - Dashboards with widgets
 * - Legacy analytics reports
 *
 * Routes:
 * - /api/v1/reports/definitions/*  - Report definitions
 * - /api/v1/reports/execute        - Execute reports
 * - /api/v1/reports/executions/*   - Execution history
 * - /api/v1/reports/schedules/*    - Scheduled reports
 * - /api/v1/reports/custom/*       - Custom reports
 * - /api/v1/dashboards/*           - Dashboards and widgets
 * - /api/v1/reports/legacy/*       - Legacy analytics
 */
export class ReportsModule {
  public router: Router;

  // Services
  public reportsService: ReportsService;
  public executionService: ReportExecutionService;
  public schedulerService: ReportSchedulerService;
  public dashboardsService: DashboardsService;
  public legacyService: LegacyReportsService;

  private dataSource: DataSource;
  private basePath: string;

  constructor(options: ReportsModuleOptions) {
    this.dataSource = options.dataSource;
    this.basePath = options.basePath || '';
    this.router = Router();
    this.initializeServices();
    this.initializeRoutes();
  }

  /**
   * Initialize all services with their repositories
   */
  private initializeServices(): void {
    // Get repositories
    const definitionRepository = this.dataSource.getRepository(ReportDefinition);
    const executionRepository = this.dataSource.getRepository(ReportExecution);
    const scheduleRepository = this.dataSource.getRepository(ReportSchedule);
    const recipientRepository = this.dataSource.getRepository(ReportRecipient);
    const scheduleExecutionRepository = this.dataSource.getRepository(ScheduleExecution);
    const customReportRepository = this.dataSource.getRepository(CustomReport);
    const dashboardRepository = this.dataSource.getRepository(Dashboard);
    const widgetRepository = this.dataSource.getRepository(DashboardWidget);
    const queryRepository = this.dataSource.getRepository(WidgetQuery);

    // Create services
    this.reportsService = new ReportsService(
      definitionRepository,
      scheduleRepository,
      recipientRepository,
      customReportRepository
    );

    this.executionService = new ReportExecutionService(
      executionRepository,
      definitionRepository,
      this.dataSource
    );

    this.schedulerService = new ReportSchedulerService(
      scheduleRepository,
      scheduleExecutionRepository,
      this.executionService
    );

    this.dashboardsService = new DashboardsService(
      dashboardRepository,
      widgetRepository,
      queryRepository,
      this.dataSource
    );

    // Legacy service for backwards compatibility
    this.legacyService = new LegacyReportsService(this.dataSource);
  }

  /**
   * Initialize routes with controllers
   */
  private initializeRoutes(): void {
    const reportsController = new ReportsController(
      this.reportsService,
      this.executionService,
      this.schedulerService
    );

    const dashboardsController = new DashboardsController(this.dashboardsService);
    const legacyController = new LegacyReportsController(this.legacyService);

    // Mount routes
    this.router.use(`${this.basePath}/reports`, reportsController.router);
    this.router.use(`${this.basePath}/dashboards`, dashboardsController.router);
    this.router.use(`${this.basePath}/reports/legacy`, legacyController.router);
  }

  /**
   * Get all entities managed by this module
   */
  static getEntities(): Function[] {
    return [
      ReportDefinition,
      ReportExecution,
      ReportSchedule,
      ReportRecipient,
      ScheduleExecution,
      Dashboard,
      DashboardWidget,
      WidgetQuery,
      CustomReport,
      DataModelEntity,
      DataModelField,
      DataModelRelationship,
    ];
  }
}
