import type { NpcGroupId, NpcId, ProjectNpc, ProjectNpcGroup } from '../../shared/types';

export function reorderNpcIds(
  npcs: ProjectNpc[],
  dragId: NpcId,
  targetId: NpcId,
  place: 'before' | 'after',
): NpcId[] {
  const ids = npcs.map((n) => n.id);
  const from = ids.indexOf(dragId);
  if (from < 0) return ids;
  ids.splice(from, 1);
  let to = ids.indexOf(targetId);
  if (to < 0) return npcs.map((n) => n.id);
  if (place === 'after') to += 1;
  ids.splice(to, 0, dragId);
  return ids;
}

/** Move NPC to end of its group block in global order. */
export function moveNpcToGroupEnd(npcs: ProjectNpc[], dragId: NpcId, groupId: NpcGroupId | null): NpcId[] {
  const updated = npcs.map((n) => (n.id === dragId ? { ...n, groupId } : n));
  const ids = updated.map((n) => n.id);
  const from = ids.indexOf(dragId);
  if (from < 0) return ids;
  ids.splice(from, 1);

  let insertAt = ids.length;
  for (let i = ids.length - 1; i >= 0; i -= 1) {
    const npc = updated.find((n) => n.id === ids[i]);
    if (npc?.groupId === groupId) {
      insertAt = i + 1;
      break;
    }
  }
  if (groupId === null) {
    for (let i = ids.length - 1; i >= 0; i -= 1) {
      const npc = updated.find((n) => n.id === ids[i]);
      if (npc?.groupId === null) {
        insertAt = i + 1;
        break;
      }
    }
  }
  ids.splice(insertAt, 0, dragId);
  return ids;
}

export function reorderSiblingGroups(
  groups: ProjectNpcGroup[],
  dragId: NpcGroupId,
  targetId: NpcGroupId,
  place: 'before' | 'after',
): NpcGroupId[] {
  const drag = groups.find((g) => g.id === dragId);
  const target = groups.find((g) => g.id === targetId);
  if (!drag || drag.parentId !== target?.parentId) return groups.map((g) => g.id);

  const parentId = drag.parentId;
  const siblingIds = groups.filter((g) => g.parentId === parentId).map((g) => g.id);
  const from = siblingIds.indexOf(dragId);
  if (from < 0) return groups.map((g) => g.id);
  siblingIds.splice(from, 1);
  let to = siblingIds.indexOf(targetId);
  if (to < 0) return groups.map((g) => g.id);
  if (place === 'after') to += 1;
  siblingIds.splice(to, 0, dragId);

  const result: NpcGroupId[] = [];
  let inserted = false;
  for (const g of groups) {
    if (g.parentId === parentId) {
      if (!inserted) {
        result.push(...siblingIds);
        inserted = true;
      }
      continue;
    }
    result.push(g.id);
  }
  return result;
}

export function flattenGroupOptions(
  nodes: { group: ProjectNpcGroup; children: unknown[] }[],
  depth = 0,
): { id: NpcGroupId; label: string }[] {
  const out: { id: NpcGroupId; label: string }[] = [];
  for (const node of nodes) {
    const prefix = depth > 0 ? '  '.repeat(depth) : '';
    out.push({ id: node.group.id, label: `${prefix}${node.group.name}` });
    out.push(...flattenGroupOptions(node.children as typeof nodes, depth + 1));
  }
  return out;
}
