import { formatInTimeZone, toDate } from 'date-fns-tz';
import { format, isValid, parse } from 'date-fns';

const TIMEZONE = 'America/New_York';

/**
 * Safely parse a date input into a valid Date object.
 * Handles YYYY-MM-DD strings by treating them at noon UTC to avoid day-shift.
 */
const safeParse = (date) => {
  if (!date) return null;
  let d;
  if (date instanceof Date) {
    d = date;
  } else if (typeof date === 'string') {
    if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
      d = new Date(`${date}T12:00:00Z`);
    } else {
      d = new Date(date);
    }
  } else if (typeof date === 'number') {
    d = new Date(date);
  } else {
    return null;
  }
  return isNaN(d.getTime()) ? null : d;
};

export const isEDT = (date) => {
  const d = safeParse(date);
  if (!d) return false;
  const timeZoneName = formatInTimeZone(d, TIMEZONE, 'z');
  return timeZoneName === 'EDT';
};

export const toEST = (date, formatStr = 'MMM d, yyyy h:mm a zzz') => {
  const d = safeParse(date);
  if (!d) return '-';
  try {
    return formatInTimeZone(d, TIMEZONE, formatStr);
  } catch (error) {
    console.error('Error converting to EST:', error);
    return '-';
  }
};

export const toESTDateString = (date) => {
  const d = safeParse(date);
  if (!d) return '';
  try {
    return formatInTimeZone(d, TIMEZONE, 'yyyy-MM-dd');
  } catch (error) {
    return '';
  }
};

export const toESTDateDisplay = (date) => toEST(date, 'MMM d, yyyy');

// ─── Convenience formatters (all output in EST) ────────────────────

/** "01/15/2026" */
export const formatDateEST = (date) => toEST(date, 'MM/dd/yyyy');

/** "January 15, 2026" */
export const formatDateLongEST = (date) => toEST(date, 'MMMM d, yyyy');

/** "Jan 15, 2026 2:30 PM EST" */
export const formatDateTimeEST = (date) => toEST(date, 'MMM d, yyyy h:mm a zzz');

/** "Jan 15, 2026 2:30 PM" (no tz label) */
export const formatDateTimeShortEST = (date) => toEST(date, 'MMM d, yyyy h:mm a');

/** "Jan 15" */
export const formatShortMonthDayEST = (date) => toEST(date, 'MMM d');

/** "Jan 15, 2026" */
export const formatShortDateEST = (date) => toEST(date, 'MMM d, yyyy');

/** "2:30 PM EST" */
export const formatTimeEST = (date) => toEST(date, 'h:mm a zzz');

/** "2:30 PM" (no tz label) */
export const formatTimeShortEST = (date) => toEST(date, 'h:mm a');

/** "Jan 15, h:mm a" for compact display */
export const formatDateTimeCompactEST = (date) => toEST(date, 'MMM d, h:mm a');

/** "yyyy-MM-dd" for form/input values */
export const formatISODateEST = (date) => toESTDateString(date);

/** Relative-style: "3 minutes ago" etc, but with EST timestamp fallback */
export const formatRelativeDateEST = (date) => {
  const d = safeParse(date);
  if (!d) return '-';
  const now = new Date();
  const diffMs = now - d;
  const diffMins = Math.floor(diffMs / 60000);
  const diffHours = Math.floor(diffMs / 3600000);
  const diffDays = Math.floor(diffMs / 86400000);

  if (diffMins < 1) return 'Just now';
  if (diffMins < 60) return `${diffMins}m ago`;
  if (diffHours < 24) return `${diffHours}h ago`;
  if (diffDays < 7) return `${diffDays}d ago`;

  return toEST(d, 'MMM d, yyyy');
};

export const nowEST = () => {
  const now = new Date();
  const estString = formatInTimeZone(now, TIMEZONE, "yyyy-MM-dd'T'HH:mm:ssXXX");
  return new Date(estString);
};

export const convertToEST = (date) => {
  return formatInTimeZone(date, TIMEZONE, "yyyy-MM-dd'T'HH:mm:ssXXX");
};

export const getCurrentESTTime = () => {
  return formatInTimeZone(new Date(), TIMEZONE, 'HH:mm');
};

export const validateESTTimeFormat = (timeString) => {
  if (!timeString) return false;
  const regex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
  return regex.test(timeString);
};

export const convertFromEST = (estTimeStr) => {
  if (!validateESTTimeFormat(estTimeStr)) return null;

  const nowInEst = formatInTimeZone(new Date(), TIMEZONE, 'yyyy-MM-dd');
  const dateTimeStr = `${nowInEst}T${estTimeStr}:00`;
  const date = toDate(dateTimeStr, { timeZone: TIMEZONE });

  return date.toISOString();
};

export const validatePaymentPlanDates = (paymentPlans) => {
  if (!Array.isArray(paymentPlans)) return false;
  let valid = true;
  paymentPlans.forEach(plan => {
    if (plan.created_at && isNaN(new Date(plan.created_at).getTime())) {
      console.error(`Invalid created_at for plan ${plan.id}`, plan.created_at);
      valid = false;
    }
    if (plan.items) {
      plan.items.forEach(item => {
        if (item.due_date && isNaN(new Date(item.due_date).getTime())) {
          console.error(`Invalid due_date for item ${item.id}`, item.due_date);
          valid = false;
        }
      });
    }
  });
  return valid;
};
