import { TZ } from '@/lib/datetime';

export type OpenNowState = 'open' | 'closed' | 'unknown';

export interface OpenNowSignal {
  state: OpenNowState;
  opensAtMinutes: number | null;
  closesAtMinutes: number | null;
}

function minutesInIsrael(now: Date): number {
  const parts = new Intl.DateTimeFormat('en-GB', {
    timeZone: TZ,
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  })
    .formatToParts(now)
    .reduce<Record<string, string>>((acc, part) => {
      if (part.type !== 'literal') acc[part.type] = part.value;
      return acc;
    }, {});

  return Number(parts.hour ?? '0') * 60 + Number(parts.minute ?? '0');
}

function parseHoursRange(hours: string): { open: number; close: number } | null {
  const match = hours.match(/^(\d{2}):(\d{2})-(\d{2}):(\d{2})$/);
  if (!match) return null;
  const [, oh, om, ch, cm] = match;
  if (!oh || !om || !ch || !cm) return null;
  return {
    open: Number(oh) * 60 + Number(om),
    close: Number(ch) * 60 + Number(cm),
  };
}

export function getOpenNowSignal(todayHours: string | null, now?: Date): OpenNowSignal;
export function getOpenNowSignal(
  todayHours: string | null,
  yesterdayHours?: string | null,
  now?: Date,
): OpenNowSignal;
export function getOpenNowSignal(
  todayHours: string | null,
  yesterdayHoursOrNow: string | null | Date = null,
  now: Date = new Date(),
): OpenNowSignal {
  const previousHours = yesterdayHoursOrNow instanceof Date ? null : yesterdayHoursOrNow;
  const currentTime = yesterdayHoursOrNow instanceof Date ? yesterdayHoursOrNow : now;
  const currentMinutes = minutesInIsrael(currentTime);

  if (previousHours && previousHours !== 'closed') {
    const yesterdayRange = parseHoursRange(previousHours);
    if (
      yesterdayRange &&
      yesterdayRange.open > yesterdayRange.close &&
      currentMinutes < yesterdayRange.close
    ) {
      return {
        state: 'open',
        opensAtMinutes: yesterdayRange.open,
        closesAtMinutes: yesterdayRange.close,
      };
    }
  }

  if (todayHours === null || todayHours === 'closed') {
    return {
      state: todayHours === null ? 'unknown' : 'closed',
      opensAtMinutes: null,
      closesAtMinutes: null,
    };
  }

  const range = parseHoursRange(todayHours);
  if (!range) {
    return { state: 'unknown', opensAtMinutes: null, closesAtMinutes: null };
  }

  const { open, close } = range;

  if (open === close) {
    return { state: 'open', opensAtMinutes: open, closesAtMinutes: close };
  }

  if (open < close) {
    return {
      state: currentMinutes >= open && currentMinutes < close ? 'open' : 'closed',
      opensAtMinutes: open,
      closesAtMinutes: close,
    };
  }

  return {
    state: currentMinutes >= open ? 'open' : 'closed',
    opensAtMinutes: open,
    closesAtMinutes: close,
  };
}
