import { Router } from 'express';
import { DataSource } from 'typeorm';
import {
  SystemSettingsService,
  TenantSettingsService,
  UserPreferencesService,
  SettingsService,
} from './services';
import {
  SystemSettingsController,
  TenantSettingsController,
  UserPreferencesController,
} from './controllers';
import {
  SystemSetting,
  PlanSetting,
  TenantSetting,
  UserPreference,
} from './entities';

/**
 * Options for configuring the Settings module
 */
export interface SettingsModuleOptions {
  dataSource: DataSource;
  basePath?: string;
  cacheTtlMs?: number;
}

/**
 * SettingsModule
 *
 * Complete settings management module for multi-tenant applications.
 *
 * Features:
 * - System settings (global configuration)
 * - Plan settings (subscription-based defaults)
 * - Tenant settings (organization overrides)
 * - User preferences (personal settings)
 *
 * Settings inheritance: system -> plan -> tenant -> user
 *
 * Usage:
 * ```typescript
 * const settingsModule = new SettingsModule({
 *   dataSource: AppDataSource,
 *   basePath: '/api/v1',
 * });
 *
 * app.use(settingsModule.router);
 * ```
 */
export class SettingsModule {
  public router: Router;
  public systemSettingsService: SystemSettingsService;
  public tenantSettingsService: TenantSettingsService;
  public userPreferencesService: UserPreferencesService;
  public settingsService: SettingsService;

  private dataSource: DataSource;
  private basePath: string;
  private cacheTtlMs: number;

  constructor(options: SettingsModuleOptions) {
    this.dataSource = options.dataSource;
    this.basePath = options.basePath || '';
    this.cacheTtlMs = options.cacheTtlMs || 5 * 60 * 1000; // 5 minutes default

    this.router = Router();
    this.initializeServices();
    this.initializeRoutes();
  }

  /**
   * Initialize all services with their repositories
   */
  private initializeServices(): void {
    const systemSettingRepository = this.dataSource.getRepository(SystemSetting);
    const planSettingRepository = this.dataSource.getRepository(PlanSetting);
    const tenantSettingRepository = this.dataSource.getRepository(TenantSetting);
    const userPreferenceRepository = this.dataSource.getRepository(UserPreference);

    // Create services
    this.systemSettingsService = new SystemSettingsService(systemSettingRepository);
    this.systemSettingsService.setCacheTtl(this.cacheTtlMs);

    this.tenantSettingsService = new TenantSettingsService(
      tenantSettingRepository,
      systemSettingRepository,
      planSettingRepository
    );

    this.userPreferencesService = new UserPreferencesService(userPreferenceRepository);

    // Create orchestrator service
    this.settingsService = new SettingsService(
      this.systemSettingsService,
      this.tenantSettingsService,
      this.userPreferencesService
    );
  }

  /**
   * Initialize routes with controllers
   */
  private initializeRoutes(): void {
    const systemSettingsController = new SystemSettingsController(this.systemSettingsService);
    const tenantSettingsController = new TenantSettingsController(this.tenantSettingsService);
    const userPreferencesController = new UserPreferencesController(this.userPreferencesService);

    // Mount routes
    this.router.use(`${this.basePath}/settings/system`, systemSettingsController.router);
    this.router.use(`${this.basePath}/settings/tenant`, tenantSettingsController.router);
    this.router.use(`${this.basePath}/settings/user`, userPreferencesController.router);
  }

  /**
   * Get all entities managed by this module
   */
  static getEntities(): Function[] {
    return [SystemSetting, PlanSetting, TenantSetting, UserPreference];
  }

  /**
   * Clear all caches in the module
   */
  clearCache(): void {
    this.systemSettingsService.clearCache();
  }
}
