import { findTimeZone, getZonedTime } from "timezone-support";
import { format, Locale } from "date-fns";
import { enGB, es, fr, de } from "date-fns/locale";
import i18n from "i18next";

const locales: Record<string, Locale> = { en: enGB, es, fr, de };

/**
 * Convierte una fecha UTC a hora local, según zona horaria IANA y lenguaje.
 */
export const formatToLocal = (
  utcDate: string | Date | null | undefined,
  tz: string = "Europe/London",
  language: string = i18n.language
): string => {
  try {
    if (!utcDate) return "";
    const zone = findTimeZone(tz);
    const utc = new Date(utcDate);
    const localTime = getZonedTime(utc, zone);

    const dateObj = new Date(
      localTime.year,
      localTime.month - 1,
      localTime.day,
      localTime.hours,
      localTime.minutes,
      localTime.seconds
    );

    const locale = locales[language] || enGB;
    return format(dateObj, "HH:mm", { locale });
  } catch (error) {
    console.error("Error formatting local time:", error);
    return "";
  }
};

/**
 * Convierte una fecha UTC a hora local, según zona horaria IANA y lenguaje.
 */
export const formatFullToLocal = (
  utcDate: string | Date | null | undefined,
  tz: string = "Europe/London",
  language: string = i18n.language
): string => {
  try {
    if (!utcDate) return "";
    const zone = findTimeZone(tz);
    const utc = new Date(utcDate);
    const localTime = getZonedTime(utc, zone);

    const dateObj = new Date(
      localTime.year,
      localTime.month - 1,
      localTime.day,
      localTime.hours,
      localTime.minutes,
      localTime.seconds
    );

    const locale = locales[language] || enGB;
    return format(dateObj, "PPpp", { locale });
  } catch (error) {
    console.error("Error formatting local time:", error);
    return "";
  }
};

/**
 * Convierte una fecha UTC a formato completo local (fecha + hora).
 */
export const dateTimeFormatter = (
  utcDate: string | Date | null | undefined,
  tz: string = "Europe/London",
  language: string = i18n.language
): string => {
  try {
    if (!utcDate) return "";
    const zone = findTimeZone(tz);
    const utc = new Date(utcDate);
    const localTime = getZonedTime(utc, zone);

    const dateObj = new Date(
      localTime.year,
      localTime.month - 1,
      localTime.day,
    );

    const locale = locales[language] || enGB;
    return format(dateObj, "PPP", { locale });
  } catch (error) {
    console.error("Error formatting datetime:", error);
    return "";
  }
};

/**
 * (Opcional) Devuelve una versión enriquecida: hora UTC, local y offset.
 */
export const getTimeWithOffset = (
  utcDate: string | Date,
  tz: string = "Europe/London"
): {
  utc: string;
  local: string;
  offsetLabel: string;
} => {
  const zone = findTimeZone(tz);
  const localTime = getZonedTime(new Date(utcDate), zone);
  const offsetHours = localTime.zoneOffset / 60;
  const offsetLabel = `UTC${offsetHours >= 0 ? "+" : ""}${offsetHours}`;
  return {
    utc: format(new Date(utcDate), "HH:mm 'UTC'"),
    local: format(
      new Date(
        localTime.year,
        localTime.month - 1,
        localTime.day,
        localTime.hours,
        localTime.minutes
      ),
      "HH:mm"
    ),
    offsetLabel,
  };
};

export const formatCalendarDay = (
  utcDate: string | Date | null | undefined,
  tz: string = "Europe/London",
  language: string = i18n.language
): { weekday: string; day: string; month: string; label: string } => {
  try {
    if (!utcDate) {
      return { weekday: "", day: "", month: "", label: "" };
    }

    const zone = findTimeZone(tz);
    const utc = new Date(utcDate);
    const localTime = getZonedTime(utc, zone);

    const dateObj = new Date(
      localTime.year,
      localTime.month - 1,
      localTime.day
    );

    const locale = locales[language] || enGB;

    const weekday = format(dateObj, "EEE", { locale }); // ej: "Mon"
    const day = format(dateObj, "d", { locale });        // ej: "10"
    const month = format(dateObj, "MMM", { locale });    // ej: "Nov"

    const label = `${weekday} ${day} ${month}`;

    return { weekday, day, month, label };
  } catch (error) {
    console.error("Error formatting calendar day:", error);
    return { weekday: "", day: "", month: "", label: "" };
  }
};