import { Injectable } from '@nestjs/common';
import { AppLoggerService } from 'src/common/services/logger.service';
import { handleKnownErrors } from 'src/common/utils/handle-error.util';
import { ERROR_CODES } from 'src/common/constants/error-string-constants';
import { SessionProviderType } from 'src/common/enum/session-provider.enum';
import { OnlineSessionProvider } from '../interfaces/online-session-provider.interface';
import { ONLINE_SESSION_LOG } from 'src/common/constants/online-session.constants';

/**
 * Maps a provider key to its implementation. Providers self-register in their
 * own `onModuleInit`, exactly like queue processors register with
 * ProcessorRegistryService — so adding a provider touches zero existing files.
 */
@Injectable()
export class OnlineSessionProviderRegistry {
  private readonly providers = new Map<SessionProviderType, OnlineSessionProvider>();

  constructor(private readonly logger: AppLoggerService) {}

  register(key: SessionProviderType, provider: OnlineSessionProvider): void {
    if (this.providers.has(key)) {
      this.logger.warn(ONLINE_SESSION_LOG.PROVIDER_OVERWRITTEN(key));
    }
    this.providers.set(key, provider);
    this.logger.log(ONLINE_SESSION_LOG.PROVIDER_REGISTERED(key));
  }

  /** Resolve a provider or throw a mapped bad-request when unsupported. */
  resolve(key: SessionProviderType): OnlineSessionProvider {
    const provider = this.providers.get(key);
    if (!provider) {
      handleKnownErrors(
        ERROR_CODES.UNSUPPORTED_ONLINE_PROVIDER,
        new Error(ONLINE_SESSION_LOG.NO_PROVIDER_REGISTERED(key)),
      );
    }
    return provider;
  }

  hasProvider(key: SessionProviderType): boolean {
    return this.providers.has(key);
  }
}
