import { renderHook } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import { describe, expect, it, vi, afterEach } from 'vitest';
import { getColumnTypeRegistry, getDataviewMenuRegistry } from '@ablogcms/plugins/core';
import type { ColumnTypeDef, ColumnServiceInterface } from '@ablogcms/components/dataview/types';
import { createColumnConfigMenu } from '@ablogcms/components/dataview/menus';
import type { AcmsContext } from '@ablogcms/url/types';
import useEntryAdminMenus, { type GetMenusContext } from './use-entry-admin-menus';
import { ENTRY_COLUMN_TYPES } from '../constants';
import type { EntryType } from '../types';

vi.mock('@ablogcms/components/dataview/menus', () => ({
  createColumnConfigMenu: vi.fn(() => ({
    id: 'column-visibility',
    label: 'column-visibility',
    renderDrawer: () => null,
  })),
}));

const wrapper = ({ children }: { children: React.ReactNode }) => <MemoryRouter>{children}</MemoryRouter>;

const createContext = (): GetMenusContext => ({
  context: {} as AcmsContext,
  searchParams: new URLSearchParams(),
  columnService: {} as ColumnServiceInterface<EntryType>,
});

// entry-admin.tsx（entry-admin 本体の一覧描画）は getEntryColumnTypes()（コア組み込み +
// ctx.dataview.registerColumnType 登録分のマージ）を columnTypes に使うが、カラム追加モーダル
// （customColumnModalProps）は素の ENTRY_COLUMN_TYPES を渡していたため、プラグインが登録した
// カラム型が一覧には出るのに「追加」モーダルの選択肢には出てこないという不整合があった。
// この特徴付けテストは、その不整合が解消されたことを固定する。
describe('useEntryAdminMenus', () => {
  afterEach(() => {
    vi.mocked(createColumnConfigMenu).mockClear();
  });

  it('レジストリが空の場合はコア組み込みの ENTRY_COLUMN_TYPES のみが customColumnModalProps に渡る（回帰なし）', () => {
    renderHook(() => useEntryAdminMenus({ getMenus: (menus) => menus, context: createContext() }), { wrapper });

    expect(createColumnConfigMenu).toHaveBeenCalledWith(
      expect.anything(),
      expect.objectContaining({ customColumnModalProps: { columnTypes: ENTRY_COLUMN_TYPES } })
    );
  });

  it('ctx.dataview.registerColumnType で登録したカラム型が customColumnModalProps.columnTypes に含まれる', () => {
    const customColumnType: ColumnTypeDef = { getValue: () => 'custom', label: 'カスタム型' };
    const unsubscribe = getColumnTypeRegistry().add('custom-column', customColumnType);

    renderHook(() => useEntryAdminMenus({ getMenus: (menus) => menus, context: createContext() }), { wrapper });

    expect(createColumnConfigMenu).toHaveBeenCalledWith(
      expect.anything(),
      expect.objectContaining({
        customColumnModalProps: {
          columnTypes: { ...ENTRY_COLUMN_TYPES, 'custom-column': customColumnType },
        },
      })
    );

    unsubscribe();
  });

  it('登録解除後は customColumnModalProps.columnTypes から除外される', () => {
    const customColumnType: ColumnTypeDef = { getValue: () => 'custom' };
    const unsubscribe = getColumnTypeRegistry().add('custom-column', customColumnType);
    unsubscribe();

    renderHook(() => useEntryAdminMenus({ getMenus: (menus) => menus, context: createContext() }), { wrapper });

    expect(createColumnConfigMenu).toHaveBeenCalledWith(
      expect.anything(),
      expect.objectContaining({ customColumnModalProps: { columnTypes: ENTRY_COLUMN_TYPES } })
    );
  });

  describe('ctx.dataview.registerMenu("entry", ...) レジストリとのマージ', () => {
    afterEach(() => {
      getDataviewMenuRegistry().remove('entry', 'plugin-menu');
    });

    it('レジストリに登録したメニューがコア定義の後ろに追加され getMenus に渡る', () => {
      getDataviewMenuRegistry().add('entry', 'plugin-menu', { id: 'plugin-menu', label: 'プラグインメニュー' });
      let received: string[] | undefined;

      renderHook(
        () =>
          useEntryAdminMenus({
            getMenus: (menus) => {
              received = menus.map((m) => m.id);
              return menus;
            },
            context: createContext(),
          }),
        { wrapper }
      );

      expect(received).toContain('plugin-menu');
      expect(received?.at(-1)).toBe('plugin-menu');
    });

    it('レジストリ登録後もレガシー getMenus（フィルタ）が最終結果に適用される', () => {
      getDataviewMenuRegistry().add('entry', 'plugin-menu', { id: 'plugin-menu', label: 'プラグインメニュー' });

      const { result } = renderHook(
        () =>
          useEntryAdminMenus({
            getMenus: (menus) => menus.filter((m) => m.id !== 'plugin-menu'),
            context: createContext(),
          }),
        { wrapper }
      );

      expect(result.current.map((m) => m.id)).not.toContain('plugin-menu');
    });
  });
});
