import { useCallback } from 'react';

import { format } from 'date-fns';

import useAuth from 'src/contexts/JWTContext';
import { getCurrentLocale } from 'src/utils/locale';
import { parseDateString } from 'src/utils/timeUtils';

type FormatDateOptions = {
  locale?: Locale;
  weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
  firstWeekContainsDate?: number;
  useAdditionalWeekYearTokens?: boolean;
  useAdditionalDayOfYearTokens?: boolean;
  localeDateStringOptions?: Intl.DateTimeFormatOptions;
};

export default function useFormatDate() {
  const { user } = useAuth();

  const formatDayWithoutYear = useCallback(
    (date: Date | string | number) => {
      try {
        const locale = getCurrentLocale(user);
        const dateToFormat = parseDateString(date);
        // Intl.DateTimeFormat is used instead of date-fns format() because it respects the locale's
        // native day/month ordering (e.g. "6 de noviembre" vs "November 6"), which would require
        // hardcoding a pattern in date-fns and break for non-European locales.
        const formatter = new Intl.DateTimeFormat(locale.code, {
          day: 'numeric',
          month: 'long',
        });
        return formatter.format(dateToFormat);
      } catch {
        return '';
      }
    },
    [user],
  );

  const formatDate = useCallback(
    (
      date: Date | number | string,
      pattern: string = 'P',
      options?: FormatDateOptions,
    ) => {
      // Patterns: https://date-fns.org/v4.1.0/docs/format
      // Default pattern: P (04/29/2024)

      try {
        const parsedDate = parseDateString(date);

        if (options?.localeDateStringOptions) {
          return new Date(parsedDate).toLocaleDateString(
            getCurrentLocale(user).code,
            options?.localeDateStringOptions,
          );
        }

        return format(parsedDate, pattern, {
          locale: getCurrentLocale(user),
          ...options,
        });
      } catch {
        return '';
      }
    },
    [user],
  );

  return { formatDate, formatDayWithoutYear };
}
