// @vitest-environment happy-dom
/**
 * UX-5.3 — command palette behaviour.
 *
 * Asserts the registry builder produces the expected command set, and that the
 * palette opens on ⌘K and lists the registered commands. Uses a jsdom render
 * harness with react-dom/client (no @testing-library dependency).
 *
 * @see docs/roadmaps/UX_INTEGRATION_BYTELYST.md (UX-5)
 */

import { describe, it, expect, beforeAll, vi } from 'vitest';
import { act, createElement } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import {
  CommandRegistryProvider,
  CommandPalette,
  useCommandPalette,
  useRegisterCommands,
} from '@bytelyst/command-palette';
import { buildCommands, type CommandMenuDeps } from '@/lib/command-registry';

beforeAll(() => {
  (globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;
});

const stubDeps = (over: Partial<CommandMenuDeps> = {}): CommandMenuDeps => ({
  navigate: vi.fn(),
  newItem: vi.fn(),
  toggleTheme: vi.fn(),
  signOut: vi.fn(),
  setProduct: vi.fn(),
  products: [{ id: 'p1', name: 'Prod One' }],
  ...over,
});

describe('buildCommands', () => {
  it('includes navigate, action and per-product switch commands', () => {
    const cmds = buildCommands(stubDeps());
    const ids = cmds.map(c => c.id);
    expect(ids).toEqual(
      expect.arrayContaining([
        'nav-overview',
        'nav-items',
        'nav-board',
        'nav-roadmap',
        'new-item',
        'toggle-theme',
        'sign-out',
        'switch-product-p1',
      ])
    );
    // Navigate commands carry an href + navigate mode.
    const overview = cmds.find(c => c.id === 'nav-overview');
    expect(overview?.mode).toBe('navigate');
    expect(overview?.href).toBe('/dashboard');
  });

  it('wires action handlers to the supplied callbacks', () => {
    const deps = stubDeps();
    const cmds = buildCommands(deps);
    cmds.find(c => c.id === 'new-item')?.run?.();
    cmds.find(c => c.id === 'switch-product-p1')?.run?.();
    expect(deps.newItem).toHaveBeenCalledTimes(1);
    expect(deps.setProduct).toHaveBeenCalledWith('p1');
  });
});

function Harness() {
  const cmdk = useCommandPalette();
  useRegisterCommands(buildCommands(stubDeps()));
  return createElement(CommandPalette, { open: cmdk.open, onClose: cmdk.hide });
}

describe('CommandPalette ⌘K', () => {
  it('opens on Cmd-K and lists registered commands', () => {
    const container = document.createElement('div');
    document.body.appendChild(container);
    let root!: Root;
    act(() => {
      root = createRoot(container);
      root.render(createElement(CommandRegistryProvider, null, createElement(Harness)));
    });

    // Closed initially — the dialog is not rendered.
    expect(container.querySelector('[data-testid="bl-cmdk"]')).toBeNull();

    // ⌘K toggles it open.
    act(() => {
      window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }));
    });
    expect(container.querySelector('[data-testid="bl-cmdk"]')).not.toBeNull();

    // Actions-tab commands are listed.
    expect(container.textContent).toContain('New item');
    expect(container.textContent).toContain('Toggle theme');
    expect(container.textContent).toContain('Sign out');

    act(() => root.unmount());
    container.remove();
  });
});
