import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { InquiryType } from '../../common/enums/inquiry-type.enum'; import { ProviderName } from '../../common/enums/provider-name.enum'; import { InquiryProvider } from '../../common/interfaces/inquiry-provider.interface'; import { InquiryRoutingConfig } from '../../config/configuration'; import { HamtaProvider } from '../implementations/hamta.provider'; import { MoallemProvider } from '../implementations/moallem.provider'; import { ParsianProvider } from '../implementations/parsian.provider'; import { TejaratNouProvider } from '../implementations/tejaratnou.provider'; /** * Factory + registry for provider instances. * Resolves providers by name and builds ordered execution chains (default + fallbacks). * Note: AMITIS is not a provider, it's an authentication service used by other providers. */ @Injectable() export class ProviderFactory { private readonly logger = new Logger(ProviderFactory.name); private readonly registry: Map; constructor( private readonly configService: ConfigService, hamta: HamtaProvider, moallem: MoallemProvider, parsian: ParsianProvider, tejaratnou: TejaratNouProvider, ) { this.registry = new Map([ [ProviderName.HAMTA, hamta], [ProviderName.MOALLEM, moallem], [ProviderName.PARSIAN, parsian], [ProviderName.TEJARATNOU, tejaratnou], ]); } getProvider(name: ProviderName): InquiryProvider | undefined { const provider = this.registry.get(name); if (!provider?.isEnabled()) { this.logger.warn(`Provider ${name} is disabled or not configured`); return undefined; } return provider; } /** * Returns providers in execution order: default first, then fallbacks. */ getProvidersForInquiry(inquiryType: InquiryType): InquiryProvider[] { const routing = this.configService.get( `inquiryRouting.${inquiryType}`, ); if (!routing) { this.logger.error(`No routing config for inquiry type ${inquiryType}`); return []; } const orderedNames = [ routing.defaultProvider, ...(routing.fallbackEnabled ? routing.fallbackProviders : []), ]; const seen = new Set(); const providers: InquiryProvider[] = []; for (const name of orderedNames) { if (seen.has(name)) continue; seen.add(name); const provider = this.getProvider(name); if (provider?.supportedInquiryTypes.includes(inquiryType)) { providers.push(provider); } } return providers; } }