import { useTranslation } from './useTranslation';
import { useAuth } from '@/lib/auth/AuthContext';
import {
  format as dateFnsFormat,
  formatDistanceToNow as dateFnsFormatDistanceToNow,
  formatDistance as dateFnsFormatDistance,
  formatRelative as dateFnsFormatRelative,
} from 'date-fns';
import { formatInTimeZone } from 'date-fns-tz';
import { enUS, es, fr, ptBR, zhCN, de, it, type Locale } from 'date-fns/locale';

/**
 * Map of i18next language codes to date-fns locales
 */
const localeMap: Record<string, Locale> = {
  'en': enUS,
  'en-US': enUS,
  'es': es,
  'es-ES': es,
  'fr': fr,
  'fr-FR': fr,
  'pt': ptBR,
  'pt-BR': ptBR,
  'zh': zhCN,
  'zh-CN': zhCN,
  'de': de,
  'de-DE': de,
  'it': it,
  'it-IT': it,
};

/**
 * Custom hook for localized date formatting using date-fns
 * Automatically applies the correct locale, timezone, and time format based on user preferences
 */
export function useLocalizedDate() {
  const { language } = useTranslation();
  const { user } = useAuth();

  // Get the locale for the current language, fallback to enUS
  const locale = localeMap[language] || enUS;

  // Get timezone from user preferences, fallback to UTC or browser timezone
  const timezone = user?.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';

  // Get time format preference (12h or 24h)
  const timeFormat = user?.preferences?.timeFormat || '12h';

  /**
   * Format a date using date-fns with the current locale and timezone
   * @param date - The date to format
   * @param formatStr - The format string (e.g., 'PPP', 'MM/dd/yyyy', 'p' for time)
   * @param options - Optional formatting options
   */
  const format = (
    date: Date | number | string,
    formatStr: string,
    options?: { useTimezone?: boolean }
  ): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;

    // Replace time format tokens with 12h/24h based on preference
    let adjustedFormat = formatStr;
    if (timeFormat === '24h') {
      // Convert 12h format to 24h format
      adjustedFormat = formatStr.replace(/h:mm a/gi, 'HH:mm').replace(/p/g, 'HH:mm');
    }

    // Use timezone if requested
    if (options?.useTimezone && timezone) {
      return formatInTimeZone(dateObj, timezone, adjustedFormat, { locale });
    }

    return dateFnsFormat(dateObj, adjustedFormat, { locale });
  };

  /**
   * Format a date as a distance to now (e.g., "2 hours ago")
   * @param date - The date to format
   * @param options - Optional options for formatDistanceToNow
   */
  const formatDistanceToNow = (
    date: Date | number | string,
    options?: { addSuffix?: boolean; includeSeconds?: boolean }
  ): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    return dateFnsFormatDistanceToNow(dateObj, { ...options, locale });
  };

  /**
   * Format the distance between two dates
   * @param date - The later date
   * @param baseDate - The earlier date
   * @param options - Optional options for formatDistance
   */
  const formatDistance = (
    date: Date | number,
    baseDate: Date | number,
    options?: { addSuffix?: boolean; includeSeconds?: boolean }
  ): string => {
    return dateFnsFormatDistance(date, baseDate, { ...options, locale });
  };

  /**
   * Format a date relative to now (e.g., "today at 5:00 PM")
   * @param date - The date to format
   * @param baseDate - Optional base date (defaults to now)
   */
  const formatRelative = (
    date: Date | number,
    baseDate?: Date | number
  ): string => {
    return dateFnsFormatRelative(date, baseDate || new Date(), { locale });
  };

  /**
   * Format a time string with the user's preferred time format
   * @param date - The date/time to format
   */
  const formatTime = (date: Date | number | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    const formatStr = timeFormat === '24h' ? 'HH:mm' : 'h:mm a';
    return dateFnsFormat(dateObj, formatStr, { locale });
  };

  /**
   * Format a date and time with the user's timezone and time format
   * @param date - The date/time to format
   */
  const formatDateTime = (date: Date | number | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    const timeFormatStr = timeFormat === '24h' ? 'HH:mm' : 'h:mm a';
    const fullFormat = `PPP ${timeFormatStr}`;

    if (timezone) {
      return formatInTimeZone(dateObj, timezone, fullFormat, { locale });
    }

    return dateFnsFormat(dateObj, fullFormat, { locale });
  };

  return {
    format,
    formatDistanceToNow,
    formatDistance,
    formatRelative,
    formatTime,
    formatDateTime,
    locale,
    timezone,
    timeFormat,
  };
}
