import { Injectable } from '@nestjs/common';
import { ErrorCode, ErrorMessages } from '../constants/error-codes';
import { ErrorResponseDto } from '../dtos/error-response.dto';

export type SupportedLocale = 'en-US' | 'es-ES' | 'fr-FR' | 'pt-BR' | 'zh-CN';

@Injectable()
export class ErrorResponseService {
  private defaultLocale: SupportedLocale = 'en-US';

  /**
   * Get localized error message
   */
  getErrorMessage(code: ErrorCode, locale?: SupportedLocale): string {
    const normalizedLocale = locale || this.defaultLocale;
    const messages = ErrorMessages[code];

    if (!messages) {
      return 'An unexpected error occurred';
    }

    return messages[normalizedLocale] || messages[this.defaultLocale];
  }

  /**
   * Create error response DTO
   */
  createErrorResponse(
    code: ErrorCode,
    statusCode: number,
    locale?: SupportedLocale,
    path?: string,
    details?: any,
  ): ErrorResponseDto {
    const message = this.getErrorMessage(code, locale);
    return new ErrorResponseDto(code, message, statusCode, path, details);
  }

  /**
   * Extract locale from request headers
   */
  extractLocale(acceptLanguage?: string): SupportedLocale {
    if (!acceptLanguage) {
      return this.defaultLocale;
    }

    // Parse Accept-Language header (e.g., "en-US,en;q=0.9,es;q=0.8")
    const locales = acceptLanguage.split(',').map((lang) => {
      const [locale] = lang.trim().split(';');
      return locale;
    });

    // Find first supported locale
    for (const locale of locales) {
      if (this.isSupportedLocale(locale)) {
        return locale as SupportedLocale;
      }

      // Try matching language code only (e.g., "en" -> "en-US")
      const languageCode = locale.split('-')[0];
      const matchedLocale = this.findLocaleByLanguage(languageCode);
      if (matchedLocale) {
        return matchedLocale;
      }
    }

    return this.defaultLocale;
  }

  /**
   * Check if locale is supported
   */
  private isSupportedLocale(locale: string): boolean {
    return ['en-US', 'es-ES', 'fr-FR', 'pt-BR', 'zh-CN'].includes(locale);
  }

  /**
   * Find locale by language code
   */
  private findLocaleByLanguage(languageCode: string): SupportedLocale | null {
    const localeMap: Record<string, SupportedLocale> = {
      en: 'en-US',
      es: 'es-ES',
      fr: 'fr-FR',
      pt: 'pt-BR',
      zh: 'zh-CN',
    };

    return localeMap[languageCode] || null;
  }
}
