import { format } from 'date-fns';
import { enUS, hu } from 'date-fns/locale';

import {
  Event,
  EventInstitutionField,
  InstitutionAddress,
  PlaceWithoutInstitution,
} from '@/types/Events';

/**
 * Resolves the locale-correct slug for a /program/[slug] link.
 * Prefers the English slug (urlEn) for English, falls back to the Hungarian
 * slug, and finally to the numeric id. Keeps the same key valid across locales.
 */
export const getEventProgramSlug = (
  event: Pick<Event, 'url' | 'urlEn' | 'id'>,
  locale: string
): string => {
  const localized = locale.startsWith('en') ? event.urlEn || event.url : event.url;
  return localized?.trim() || event.id.toString();
};

const getAddressLocationString = (
  address: InstitutionAddress | PlaceWithoutInstitution
): string | null => {
  if (!address) return null;

  const parts: string[] = [];
  const cleanZip = address.zip ? address.zip.replace(/\.0$/, '') : null;
  const locationPart = [cleanZip, address.city].filter(Boolean).join(' ');

  if (locationPart) {
    parts.push(locationPart);
  }

  if (address.address1) {
    parts.push(address.address1);
  }

  return parts.length > 0 ? parts.join(', ') : null;
};

// Build location string from institution field with organizational unit and venue
export const getInstitutionLocationString = (
  institutionField: EventInstitutionField
): string | null => {
  if (!institutionField) return null;

  const { intezmeny, szervezetiEgyseg, helyszin } = institutionField;
  const parts: string[] = [];

  // Add institution name
  if (intezmeny?.nev) {
    parts.push(intezmeny.nev);
  }

  // Add organizational units (egyseg1, egyseg2, egyseg3) if exist
  if (szervezetiEgyseg?.egyseg1) {
    parts.push(szervezetiEgyseg.egyseg1);
  }
  if (szervezetiEgyseg?.egyseg2) {
    parts.push(szervezetiEgyseg.egyseg2);
  }
  if (szervezetiEgyseg?.egyseg3) {
    parts.push(szervezetiEgyseg.egyseg3);
  }

  // Add venue (helyszin) if exists
  if (helyszin) {
    parts.push(helyszin);
  }

  // Determine which address to use: organizational unit's or institution's
  const address = szervezetiEgyseg?.cim || intezmeny?.intezmenyCime;
  const addressLocation = address ? getAddressLocationString(address) : null;

  if (addressLocation) {
    parts.push(addressLocation);
  }

  return parts.length > 0 ? parts.join(', ') : null;
};

export const getPlaceLocationString = (place: PlaceWithoutInstitution): string | null => {
  return getAddressLocationString(place);
};

export const getEventLocationString = (event: Event): string | null => {
  const institutionField = event.intezmeny?.[0];
  if (institutionField) {
    return getInstitutionLocationString(institutionField);
  }

  if (event.hely) {
    return getPlaceLocationString(event.hely);
  }

  return null;
};

export const getEventCoordinates = (event: Event): string | null => {
  const institutionField = event.intezmeny?.[0];
  const institutionAddress =
    institutionField?.szervezetiEgyseg?.cim || institutionField?.intezmeny?.intezmenyCime;

  if (institutionAddress?.koordinatak) {
    return institutionAddress.koordinatak;
  }

  return event.hely?.koordinatak || null;
};

// Convert UTC date string to Budapest timezone
export const toBudapestDate = (utcString: string): Date => {
  const utcDate = new Date(utcString);
  const budapestString = utcDate.toLocaleString('en-US', {
    timeZone: 'Europe/Budapest',
  });
  return new Date(budapestString);
};

export const getEventStartDateString = (
  event: Event,
  isLongFormat: boolean = false,
  locale: string = 'hu'
): string => {
  const startDate = toBudapestDate(event.kezdete);
  if (isNaN(startDate.getTime())) return '';

  const includeTime = !event.kezdeteDatum;
  const dateLocale = locale === 'en' ? enUS : hu;

  if (isLongFormat) {
    // Long format: "November 5, 2025 (Tuesday), 18:00" or "November 5, 2025 (Tuesday)"
    const formatString =
      locale === 'en'
        ? includeTime
          ? 'MMMM d, yyyy (EEEE), HH:mm'
          : 'MMMM d, yyyy (EEEE)'
        : includeTime
          ? 'yyyy. MMMM d. (EEEE), HH:mm'
          : 'yyyy. MMMM d. (EEEE)';
    return format(startDate, formatString, { locale: dateLocale });
  } else {
    // Short format: "2025.11.5." or "11/05/2025"
    const formatString = locale === 'en' ? 'MM/dd/yyyy' : 'yyyy.MM.dd.';
    return format(startDate, formatString, { locale: dateLocale });
  }
};

const getEventEndDateString = (
  event: Event,
  isLongFormat: boolean = false,
  locale: string = 'hu'
): string | null => {
  if (!event.vege) return null;
  const endDate = toBudapestDate(event.vege);
  if (isNaN(endDate.getTime())) return null;

  const includeTime = !event.vegeDatum;
  const dateLocale = locale === 'en' ? enUS : hu;

  if (isLongFormat) {
    // Long format: "November 5, 2025 (Tuesday), 18:00" or "November 5, 2025 (Tuesday)"
    const formatString =
      locale === 'en'
        ? includeTime
          ? 'MMMM d, yyyy (EEEE), HH:mm'
          : 'MMMM d, yyyy (EEEE)'
        : includeTime
          ? 'yyyy. MMMM d. (EEEE), HH:mm'
          : 'yyyy. MMMM d. (EEEE)';
    return format(endDate, formatString, { locale: dateLocale });
  } else {
    // Short format: "2025.11.5." or "11/05/2025"
    const formatString = locale === 'en' ? 'MM/dd/yyyy' : 'yyyy.MM.dd.';
    return format(endDate, formatString, { locale: dateLocale });
  }
};

// Create string interval for event
export const getEventTimeIntervalString = (
  event: Event,
  isLongFormat: boolean = false,
  locale: string = 'hu'
): string => {
  const startStr = getEventStartDateString(event, isLongFormat, locale);
  const endStr = getEventEndDateString(event, isLongFormat, locale);

  if (endStr) {
    return `${startStr} – ${endStr}`;
  }
  return startStr;
};

export const getEventCultTypeLabel = (event: Event): string => {
  return event.kulturalisAltipus?.[0]?.nev || event.kulturalisTipus?.[0]?.nev || '';
};
