/**
 * Interactive item selection. Uses @clack/prompts when TTY, falls back to numbered list.
 */
export async function selectItem<T>(
  items: T[],
  opts: {
    message: string;
    render: (item: T) => string;
    emptyMessage?: string;
  },
): Promise<T | undefined> {
  if (items.length === 0) {
    console.log(opts.emptyMessage ?? 'No items found.');
    return undefined;
  }

  const isTTY = process.stdin.isTTY;

  if (isTTY) {
    try {
      const { select } = await import('@clack/prompts');
      const result = await select({
        message: opts.message,
        options: items.map((item, i) => ({
          value: i,
          label: opts.render(item),
        })),
      });

      if (typeof result === 'symbol') {
        return undefined;
      }

      return items[result as number];
    } catch {
      // Fall through to non-interactive
    }
  }

  // Non-interactive: display numbered list and read a number
  console.log(`\n${opts.message}\n`);
  for (let i = 0; i < items.length; i++) {
    console.log(`  ${i + 1}. ${opts.render(items[i]!)}`);
  }

  const readline = await import('node:readline');
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  const answer = await new Promise<string>((resolve) => rl.question('\nSelect: ', resolve));
  rl.close();

  const index = parseInt(answer, 10) - 1;
  if (isNaN(index) || index < 0 || index >= items.length) {
    console.error('Invalid selection.');
    return undefined;
  }

  return items[index];
}
