import { resolveTransitVariant, type TravelTimeEntry } from '../hooks/useTravelTime';

function mergeTimeRanges(
  current: [number, number] | null,
  next: [number, number] | null
): [number, number] | null {
  if (!current) return next;
  if (!next) return current;
  return [Math.max(current[0], next[0]), Math.min(current[1], next[1])];
}

/**
 * Dedupe key includes the resolved transit variant so distinct toggle
 * combinations (e.g. `transit` vs `transit-no-change`) for the same slug
 * are kept as separate filters rather than collapsed.
 */
function entryDedupeKey(entry: TravelTimeEntry): string {
  return `${resolveTransitVariant(entry)}:${entry.slug}`;
}

export function dedupeTravelTimeEntries(entries: TravelTimeEntry[]): TravelTimeEntry[] {
  const result: TravelTimeEntry[] = [];
  const indexByKey = new Map<string, number>();

  for (const entry of entries) {
    if (!entry.slug) {
      result.push(entry);
      continue;
    }

    const key = entryDedupeKey(entry);
    const existingIndex = indexByKey.get(key);
    if (existingIndex == null) {
      indexByKey.set(key, result.length);
      result.push({ ...entry });
      continue;
    }

    const existing = result[existingIndex];
    result[existingIndex] = {
      ...existing,
      label: existing.label || entry.label,
      timeRange: mergeTimeRanges(existing.timeRange, entry.timeRange),
      useBest: existing.useBest || entry.useBest,
      // noChange/oneChange/noBuses are part of the dedupe key, so for two
      // entries to collide here they must already have matching flags. Carry
      // them through explicitly so unset (undefined) doesn't clobber set
      // (false/true).
      noChange: existing.noChange ?? entry.noChange,
      oneChange: existing.oneChange ?? entry.oneChange,
      noBuses: existing.noBuses ?? entry.noBuses,
    };
  }

  return result;
}

export function buildTravelParam(
  entries: TravelTimeEntry[],
  excludeFieldKey?: string,
  includeUnboundedExcludedRange = false
): string {
  const segments: string[] = [];

  for (const entry of dedupeTravelTimeEntries(entries)) {
    if (!entry.slug) continue;

    const serverMode = resolveTransitVariant(entry);
    let segment = `${serverMode}:${entry.slug}`;
    if (entry.useBest) segment += ':best';

    const isExcluded = excludeFieldKey === `tt_${serverMode}_${entry.slug}`;
    if (isExcluded && includeUnboundedExcludedRange) {
      segment += ':0:1440';
    } else if (!isExcluded && entry.timeRange) {
      segment += `:${entry.timeRange[0]}:${entry.timeRange[1]}`;
    }

    segments.push(segment);
  }

  return segments.join('|');
}
