import type { Breakpoint, BreakpointKey } from './types';

/** Smallest to largest. `desktop` is the base. */
export const BP_ORDER_ASC: BreakpointKey[] = [
  'mobile',
  'mobile_large',
  'tablet',
  'tablet_large',
  'laptop',
  'desktop',
  'widescreen',
];

export const DEFAULT_BREAKPOINTS: Breakpoint[] = [
  { key: 'mobile', label: 'Mobile', value: 767, direction: 'max', enabled: true, icon: 'smartphone' },
  { key: 'mobile_large', label: 'Mobile Large', value: 880, direction: 'max', enabled: false, icon: 'smartphone-large' },
  { key: 'tablet', label: 'Tablet', value: 1024, direction: 'max', enabled: true, icon: 'tablet' },
  { key: 'tablet_large', label: 'Tablet Large', value: 1200, direction: 'max', enabled: false, icon: 'tablet-large' },
  { key: 'laptop', label: 'Laptop', value: 1366, direction: 'max', enabled: false, icon: 'laptop' },
  { key: 'desktop', label: 'Desktop', value: 0, direction: 'base', enabled: true, icon: 'monitor' },
  { key: 'widescreen', label: 'Widescreen', value: 2400, direction: 'min', enabled: false, icon: 'tv' },
];

export function enabledBreakpoints(bps: Breakpoint[]): Breakpoint[] {
  return bps.filter((b) => b.enabled);
}

/**
 * Order in which CSS blocks must be emitted so that the desktop-first cascade works:
 * base, then max-width queries from largest to smallest, then min-width (widescreen).
 */
export function cssEmitOrder(bps: Breakpoint[]): Breakpoint[] {
  const enabled = enabledBreakpoints(bps);
  const base = enabled.filter((b) => b.direction === 'base');
  const max = enabled.filter((b) => b.direction === 'max').sort((a, b) => b.value - a.value);
  const min = enabled.filter((b) => b.direction === 'min').sort((a, b) => a.value - b.value);
  return [...base, ...max, ...min];
}

export function mediaQuery(bp: Breakpoint): string | null {
  if (bp.direction === 'base') return null;
  return bp.direction === 'max' ? `@media (max-width: ${bp.value}px)` : `@media (min-width: ${bp.value}px)`;
}

/**
 * Fallback chain for reading the effective value at `key`: the breakpoint itself, then every enabled
 * larger breakpoint up to desktop. Widescreen falls back straight to desktop.
 */
export function fallbackChain(key: BreakpointKey, bps: Breakpoint[]): BreakpointKey[] {
  if (key === 'desktop') return ['desktop'];
  if (key === 'widescreen') return ['widescreen', 'desktop'];
  const enabled = new Set(enabledBreakpoints(bps).map((b) => b.key));
  const start = BP_ORDER_ASC.indexOf(key);
  const chain: BreakpointKey[] = [];
  for (let i = start; i < BP_ORDER_ASC.length; i++) {
    const k = BP_ORDER_ASC[i];
    if (k === 'widescreen') break;
    if (k === key || enabled.has(k) || k === 'desktop') chain.push(k);
  }
  return chain;
}

/** Larger enabled breakpoints (excluding itself), nearest first. Used to detect overrides. */
export function largerBreakpoints(key: BreakpointKey, bps: Breakpoint[]): BreakpointKey[] {
  return fallbackChain(key, bps).slice(1);
}

/** Width the canvas iframe should take for a breakpoint (null = fill). */
export function canvasWidth(bp: Breakpoint): number | null {
  if (bp.direction === 'base') return null;
  return bp.value;
}

export function findBreakpoint(bps: Breakpoint[], key: BreakpointKey): Breakpoint {
  return bps.find((b) => b.key === key) ?? DEFAULT_BREAKPOINTS.find((b) => b.key === key)!;
}
