import { describe, it, expect, vi } from 'vitest';
import resolveCommands from './resolveCommands';
import createMockEditor from '../config/blocks/__tests__/createMockEditor';
import type { CommandItem } from '../types';

const buildCmd = (name: string): CommandItem => ({
  name,
  label: name,
  description: name,
  iconName: 'title',
  isTextMenu: false,
  isDisabled: () => false,
});

describe('resolveCommands', () => {
  it('定義のある type は createActions の結果を CommandItem にマージする', () => {
    const recordUsage = vi.fn();
    const cmd = buildCmd('paragraph');

    const result = resolveCommands([cmd], recordUsage);

    expect(result).toHaveLength(1);
    expect(result[0].name).toBe('paragraph');
    expect(typeof result[0].action).toBe('function');
    expect(typeof result[0].convert).toBe('function');
    expect(typeof result[0].isDisabled).toBe('function');
    expect(typeof result[0].isActive).toBe('function');
  });

  it('定義のない type は結果から除外される', () => {
    const recordUsage = vi.fn();
    const result = resolveCommands([buildCmd('unknownBlock')], recordUsage);

    expect(result).toEqual([]);
  });

  it('複数 commands のうち、定義のあるものだけが残る', () => {
    const result = resolveCommands([buildCmd('paragraph'), buildCmd('unknownBlock'), buildCmd('heading2')], () => {});

    expect(result.map((c) => c.name)).toEqual(['paragraph', 'heading2']);
  });

  it('action を実行すると渡した recordUsage が呼ばれる', () => {
    const recordUsage = vi.fn();
    const mock = createMockEditor();
    const cmd = buildCmd('paragraph');

    const [resolved] = resolveCommands([cmd], recordUsage);
    resolved.action!(mock.editor);

    expect(recordUsage).toHaveBeenCalledTimes(1);
  });

  it('元の CommandItem のフィールド (label, class, aliases 等) は維持される', () => {
    const cmd: CommandItem = {
      ...buildCmd('paragraph'),
      label: 'カスタム段落',
      class: 'lead',
      aliases: ['p', 'lead'],
    };

    const [resolved] = resolveCommands([cmd], () => {});

    expect(resolved.label).toBe('カスタム段落');
    expect(resolved.class).toBe('lead');
    expect(resolved.aliases).toEqual(['p', 'lead']);
  });

  it('空配列を渡したら空配列を返す', () => {
    expect(resolveCommands([], () => {})).toEqual([]);
  });
});
