import { ITemplateService, TemplateInfo, TemplateValidationResult } from '../interfaces/template.interface';
import { EmailProviderType } from '../interfaces/email-options.interface';
import { SendGridTemplateService } from './templates/sendgrid-template.service';
import { SesTemplateService } from './templates/ses-template.service';
import { SendGridConfig, SesConfig } from '../interfaces/email-options.interface';
import { Logger } from '../utils/logger';
import { ConfigurationError } from '../errors';

export class TemplateManagerService {
  private templateServices: Map<EmailProviderType, ITemplateService> = new Map();
  private logger: Logger;

  constructor() {
    this.logger = Logger.getInstance();
  }

  /**
   * Register a template service for a specific provider
   */
  registerTemplateService(provider: EmailProviderType, service: ITemplateService): void {
    this.templateServices.set(provider, service);
    this.logger.debug(`Template service registered for provider: ${provider}`);
  }

  /**
   * Register SendGrid template service
   */
  registerSendGridService(config: SendGridConfig): void {
    const service = new SendGridTemplateService(config);
    this.registerTemplateService(EmailProviderType.SENDGRID, service);
  }

  /**
   * Register SES template service
   */
  registerSesService(config: SesConfig): void {
    const service = new SesTemplateService(config);
    this.registerTemplateService(EmailProviderType.SES, service);
  }

  /**
   * Check if a template service is available for a provider
   */
  hasTemplateService(provider: EmailProviderType): boolean {
    return this.templateServices.has(provider);
  }

  /**
   * Get template service for a specific provider
   */
  getTemplateService(provider: EmailProviderType): ITemplateService {
    const service = this.templateServices.get(provider);
    if (!service) {
      throw new ConfigurationError(`Template service not available for provider: ${provider}`);
    }
    return service;
  }

  /**
   * Render template using the appropriate service
   */
  async renderTemplate(
    templateId: string,
    data: Record<string, any>,
    provider: EmailProviderType
  ): Promise<string> {
    const service = this.getTemplateService(provider);
    return service.renderTemplate(templateId, data, provider);
  }

  /**
   * Validate template using the appropriate service
   */
  async validateTemplate(
    templateId: string,
    provider: EmailProviderType
  ): Promise<boolean> {
    const service = this.getTemplateService(provider);
    return service.validateTemplate(templateId, provider);
  }

  /**
   * Get template info using the appropriate service
   */
  async getTemplateInfo(
    templateId: string,
    provider: EmailProviderType
  ): Promise<TemplateInfo> {
    const service = this.getTemplateService(provider);
    return service.getTemplateInfo(templateId, provider);
  }

  /**
   * Validate template with detailed results
   */
  async validateTemplateWithDetails(
    templateId: string,
    data: Record<string, any>,
    provider: EmailProviderType
  ): Promise<TemplateValidationResult> {
    const service = this.getTemplateService(provider);
    
    // Check if the service has the extended validation method
    if ('validateTemplateWithDetails' in service) {
      return (service as any).validateTemplateWithDetails(templateId, data);
    }
    
    // Fallback to basic validation
    const isValid = await service.validateTemplate(templateId, provider);
    return {
      isValid,
      errors: isValid ? [] : [`Template validation failed: ${templateId}`],
      warnings: [],
      variables: [],
      missingVariables: []
    };
  }

  /**
   * List available templates for a provider
   */
  async listTemplates(provider: EmailProviderType): Promise<string[]> {
    const service = this.getTemplateService(provider);
    
    // Check if the service has the listTemplates method
    if ('listTemplates' in service) {
      return (service as any).listTemplates();
    }
    
    // Fallback: return empty array
    this.logger.warn(`Provider ${provider} does not support listing templates`);
    return [];
  }

  /**
   * Get all available template services
   */
  getAvailableProviders(): EmailProviderType[] {
    return Array.from(this.templateServices.keys());
  }

  /**
   * Clear all registered template services
   */
  clearServices(): void {
    this.templateServices.clear();
    this.logger.debug('All template services cleared');
  }

  /**
   * Get service statistics
   */
  getServiceStats(): Record<string, any> {
    const stats: Record<string, any> = {
      totalServices: this.templateServices.size,
      availableProviders: this.getAvailableProviders(),
      services: {}
    };

    for (const [provider, service] of this.templateServices.entries()) {
      stats.services[provider] = {
        serviceName: service.constructor.name,
        hasExtendedValidation: 'validateTemplateWithDetails' in service,
        hasListTemplates: 'listTemplates' in service
      };
    }

    return stats;
  }
}
