import type { Scene, SceneId } from '../types';

function sceneCreatedAtSortKey(sceneId: string): number {
  const last = sceneId.split('_').at(-1) ?? '';
  const n = Number.parseInt(last, 16);
  return Number.isFinite(n) ? n : 0;
}

/** Порядок по умолчанию: новее выше (как раньше по timestamp в id). */
export function defaultSceneListOrder(scenes: Record<SceneId, Scene>): SceneId[] {
  return (Object.keys(scenes) as SceneId[]).sort(
    (a, b) => sceneCreatedAtSortKey(b) - sceneCreatedAtSortKey(a),
  );
}

/**
 * Нормализует порядок: убирает отсутствующие id, добавляет новые в конец
 * (новые без записи в order — по умолчанию в «хвост» относительно сохранённого порядка;
 * при создании сцены мы сами prepend'им).
 */
export function reconcileSceneListOrder(
  scenes: Record<SceneId, Scene>,
  order: readonly SceneId[] | null | undefined,
): SceneId[] {
  const ids = new Set(Object.keys(scenes) as SceneId[]);
  if (ids.size === 0) return [];
  if (!order || order.length === 0) return defaultSceneListOrder(scenes);

  const seen = new Set<SceneId>();
  const next: SceneId[] = [];
  for (const id of order) {
    if (!ids.has(id) || seen.has(id)) continue;
    next.push(id);
    seen.add(id);
  }
  for (const id of defaultSceneListOrder(scenes)) {
    if (seen.has(id)) continue;
    next.push(id);
  }
  return next;
}

export function prependSceneListOrder(order: readonly SceneId[], sceneId: SceneId): SceneId[] {
  return [sceneId, ...order.filter((id) => id !== sceneId)];
}

export function removeFromSceneListOrder(order: readonly SceneId[], sceneId: SceneId): SceneId[] {
  return order.filter((id) => id !== sceneId);
}

export function moveSceneInListOrder(
  order: readonly SceneId[],
  draggedId: SceneId,
  targetId: SceneId,
  place: 'before' | 'after',
): SceneId[] {
  if (draggedId === targetId) return [...order];
  if (!order.includes(draggedId) || !order.includes(targetId)) return [...order];
  const without = order.filter((id) => id !== draggedId);
  const targetIndex = without.indexOf(targetId);
  if (targetIndex < 0) return [...order];
  const insertAt = place === 'before' ? targetIndex : targetIndex + 1;
  const next = [...without];
  next.splice(insertAt, 0, draggedId);
  return next;
}
