import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Command } from 'commander';

// ─── Mocks ──────────────────────────────────────────────────────────────────
// These mocks prevent any real disk/network access during tests.

vi.mock('./gateway/login.js', () => ({
  getGatewayUrl: vi.fn().mockReturnValue('http://localhost:14242'),
}));

vi.mock('./gateway/token-ops.js', () => ({
  requireSession: vi.fn().mockResolvedValue('better-auth.session_token=test'),
}));

// Global fetch is never called in smoke tests (no actions invoked).

import { registerAuthCommand } from './auth.js';

// ─── Helpers ─────────────────────────────────────────────────────────────────

function buildTestProgram(): Command {
  const program = new Command('mosaic').exitOverride();
  registerAuthCommand(program);
  return program;
}

function findCommand(program: Command, ...path: string[]): Command | undefined {
  let current: Command = program;
  for (const name of path) {
    const found = current.commands.find((c) => c.name() === name);
    if (!found) return undefined;
    current = found;
  }
  return current;
}

// ─── Tests ───────────────────────────────────────────────────────────────────

describe('registerAuthCommand', () => {
  let program: Command;

  beforeEach(() => {
    vi.clearAllMocks();
    program = buildTestProgram();
  });

  it('registers the top-level auth command', () => {
    const authCmd = findCommand(program, 'auth');
    expect(authCmd).toBeDefined();
    expect(authCmd?.name()).toBe('auth');
  });

  describe('auth users', () => {
    it('registers the users subcommand', () => {
      const usersCmd = findCommand(program, 'auth', 'users');
      expect(usersCmd).toBeDefined();
    });

    it('registers users list with --limit flag', () => {
      const listCmd = findCommand(program, 'auth', 'users', 'list');
      expect(listCmd).toBeDefined();
      const limitOpt = listCmd?.options.find((o) => o.long === '--limit');
      expect(limitOpt).toBeDefined();
    });

    it('registers users create', () => {
      const createCmd = findCommand(program, 'auth', 'users', 'create');
      expect(createCmd).toBeDefined();
    });

    it('registers users delete with --yes flag', () => {
      const deleteCmd = findCommand(program, 'auth', 'users', 'delete');
      expect(deleteCmd).toBeDefined();
      const yesOpt = deleteCmd?.options.find((o) => o.long === '--yes');
      expect(yesOpt).toBeDefined();
    });
  });

  describe('auth sso', () => {
    it('registers the sso subcommand', () => {
      const ssoCmd = findCommand(program, 'auth', 'sso');
      expect(ssoCmd).toBeDefined();
    });

    it('registers sso list', () => {
      const listCmd = findCommand(program, 'auth', 'sso', 'list');
      expect(listCmd).toBeDefined();
    });

    it('registers sso test', () => {
      const testCmd = findCommand(program, 'auth', 'sso', 'test');
      expect(testCmd).toBeDefined();
    });
  });

  describe('auth sessions', () => {
    it('registers the sessions subcommand', () => {
      const sessCmd = findCommand(program, 'auth', 'sessions');
      expect(sessCmd).toBeDefined();
    });

    it('registers sessions list', () => {
      const listCmd = findCommand(program, 'auth', 'sessions', 'list');
      expect(listCmd).toBeDefined();
    });
  });

  it('all top-level auth subcommand names are correct', () => {
    const authCmd = findCommand(program, 'auth');
    expect(authCmd).toBeDefined();
    const names = authCmd!.commands.map((c) => c.name()).sort();
    expect(names).toEqual(['sessions', 'sso', 'users']);
  });
});
