import { describe, it, expect } from 'vitest';
import { createPrompter } from './prompts.js';
import { createInterface } from 'readline/promises';
import { Readable, Writable } from 'stream';

function mockReadline(inputs: string[]) {
  let idx = 0;
  const input = new Readable({
    read() {
      if (idx < inputs.length) {
        this.push(inputs[idx++] + '\n');
      } else {
        this.push(null);
      }
    },
  });
  const output = new Writable({ write(_, __, cb) { cb(); } });
  return createInterface({ input, output });
}

describe('prompts', () => {
  describe('ask', () => {
    it('returns user input', async () => {
      const rl = mockReadline(['hello']);
      const p = createPrompter(rl);
      expect(await p.ask('Name?')).toBe('hello');
    });

    it('returns default on empty input', async () => {
      const rl = mockReadline(['']);
      const p = createPrompter(rl);
      expect(await p.ask('Name?', 'world')).toBe('world');
    });
  });

  describe('confirm', () => {
    it('returns true for Y', async () => {
      const rl = mockReadline(['Y']);
      const p = createPrompter(rl);
      expect(await p.confirm('Ok?')).toBe(true);
    });

    it('returns false for n', async () => {
      const rl = mockReadline(['n']);
      const p = createPrompter(rl);
      expect(await p.confirm('Ok?')).toBe(false);
    });

    it('defaults to true when defaultYes=true and input empty', async () => {
      const rl = mockReadline(['']);
      const p = createPrompter(rl);
      expect(await p.confirm('Ok?', true)).toBe(true);
    });

    it('defaults to false when defaultYes=false and input empty', async () => {
      const rl = mockReadline(['']);
      const p = createPrompter(rl);
      expect(await p.confirm('Ok?', false)).toBe(false);
    });
  });

  describe('choose', () => {
    it('returns selected option by number', async () => {
      const rl = mockReadline(['2']);
      const p = createPrompter(rl);
      const result = await p.choose('Pick:', [
        { label: 'A', value: 'a' },
        { label: 'B', value: 'b' },
        { label: 'C', value: 'c' },
      ]);
      expect(result).toBe('b');
    });

    it('returns first option on empty input', async () => {
      const rl = mockReadline(['']);
      const p = createPrompter(rl);
      const result = await p.choose('Pick:', [
        { label: 'A', value: 'a' },
        { label: 'B', value: 'b' },
      ]);
      expect(result).toBe('a');
    });
  });

  describe('password', () => {
    it('returns input', async () => {
      const rl = mockReadline(['secret123']);
      const p = createPrompter(rl);
      expect(await p.password('Key:')).toBe('secret123');
    });
  });
});
