import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { isLocale } from 'class-validator';
import { RequestHeaderFieldsTooLargeException } from '../../../shared/exceptions/http/request-header-fields-too-large.exception';

const DEFAULT_LOCALE = 'pt-BR';

export const AcceptLanguage = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();

    const acceptLanguage = request.headers['accept-language'];

    if (!acceptLanguage) return DEFAULT_LOCALE;

    if (acceptLanguage.length > 128)
      throw new RequestHeaderFieldsTooLargeException(
        "Maximum allowed size for 'Accept-Language' header is 128 characters",
      );

    const locales = acceptLanguage
      .split(',')
      .map((weightedLocale: string) => {
        const [locale, weight = 1] = weightedLocale.split(';q=');

        if (typeof weight === 'number') return { locale, weight };

        const _weight = Number(weight);

        return { locale, weight: Number.isNaN(weight) ? 0 : _weight };
      })
      .sort(({ weight: weight1 }, { weight: weight2 }) => weight2 - weight1)
      .flatMap(({ locale }) => {
        if (locale === '*') return [];

        if (isLocale(locale)) return [locale];

        return [];
      });

    const [locale] = locales;

    return locale ?? DEFAULT_LOCALE;
  },
);
