import { describe, it, expect, vi } from 'vitest';
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { NavigationEditor } from './navigation-editor';

// MediaInsert / MediaDropArea は redux/redux-saga を内包し、ボタン・チェックボックス置き換えの
// 確認には不要な非同期処理を伴うためスタブ化する
vi.mock('@ablogcms/media/components/media-insert/media-insert', () => ({
  default: () => null,
}));
vi.mock('@ablogcms/media/components/media-droparea/media-droparea', () => ({
  default: () => <div data-testid="media-droparea-stub" />,
}));
vi.mock('@ablogcms/components/tooltip', () => ({
  Tooltip: () => null,
}));

type NavigationEditorProps = React.ComponentProps<typeof NavigationEditor>;
type NavigationItem = NavigationEditorProps['items'][number];

const message: NavigationEditorProps['message'] = {
  open: '公開',
  label: 'ラベル',
  detail: '詳細',
  add: '追加',
  remove: '削除',
  attr: '属性',
  child_attr: '子要素の属性',
};

const buildItem = (overrides: Partial<NavigationItem> = {}): NavigationItem =>
  ({
    id: 1,
    uuid: 'item-uuid-1',
    parent: null,
    navigation_label: 'トップ',
    navigation_uri: 'https://example.com/',
    navigation_attr: '',
    navigation_a_attr: '',
    navigation_target: false,
    navigation_publish: true,
    navigation_media: null,
    navigation_media_type: '',
    navigation_media_thumbnail: '',
    toggle: false,
    hide: true,
    ...overrides,
  }) as NavigationItem;

describe('NavigationEditor', () => {
  it('公開チェックボックスが Checkbox 由来の acms-admin-form-checkbox 構造とラベルを維持する', () => {
    render(<NavigationEditor items={[buildItem()]} message={message} />);

    const checkbox = screen.getByRole('checkbox', { name: message.open }) as HTMLInputElement;
    expect(checkbox).toHaveAttribute('value', 'on');
    expect(checkbox).toBeChecked();
    // Checkbox は div.acms-admin-form-checkbox > input + label という構造で描画する
    expect(checkbox.parentElement).toHaveClass('acms-admin-form-checkbox');
    expect(checkbox.parentElement?.querySelector('i.acms-admin-ico-checkbox')).not.toBeNull();
  });

  it('詳細ボタンが unstyled な Button 由来で acms-admin-btn-admin クラスを維持し、クリックで詳細欄をトグルする', async () => {
    const user = userEvent.setup();
    render(<NavigationEditor items={[buildItem()]} message={message} enableMedia />);

    const detailButton = screen.getByRole('button', { name: message.detail });
    expect(detailButton).toHaveClass('acms-admin-btn-admin');
    expect(detailButton).toHaveAttribute('aria-expanded', 'false');

    // クリック前は詳細欄（別タブで開くチェックボックス・メディア選択ボタン）は存在しない
    expect(screen.queryByRole('checkbox', { name: '別タブで開く' })).toBeNull();

    await user.click(detailButton);

    expect(detailButton).toHaveAttribute('aria-expanded', 'true');
    const targetCheckbox = screen.getByRole('checkbox', { name: '別タブで開く' }) as HTMLInputElement;
    expect(targetCheckbox).toHaveAttribute('value', '_blank');
    expect(targetCheckbox.parentElement).toHaveClass('acms-admin-form-checkbox');

    const mediaButton = screen.getByRole('button', { name: 'メディアから選択' });
    expect(mediaButton).toHaveClass('acms-admin-btn-admin');
  });

  it('追加ボタンと削除ボタンが元のクラスを維持する', () => {
    render(<NavigationEditor items={[buildItem()]} message={message} />);

    const addButton = screen.getByRole('button', { name: message.add });
    expect(addButton).toHaveClass('acms-admin-btn-admin');

    const removeButton = screen.getByRole('button', { name: message.remove });
    expect(removeButton).toHaveClass('acms-admin-btn', 'acms-admin-btn-danger');
  });

  it('子要素を持つ場合、折りたたみボタンが acms-admin-btn-admin acms-admin-nested-collapse-btn を維持する', () => {
    const parent = buildItem({ id: 1, uuid: 'parent' });
    const child = buildItem({ id: 2, uuid: 'child', parent: 1 });
    render(<NavigationEditor items={[parent, child]} message={message} />);

    const collapseButton = screen.getByRole('button', {
      name: (_, element) => element.getAttribute('data-tooltip-content') === 'navigation.show_child_items',
    });
    expect(collapseButton).toHaveClass('acms-admin-btn-admin', 'acms-admin-nested-collapse-btn');
  });

  it('子要素を持たない場合、折りたたみボタンは表示されない', () => {
    render(<NavigationEditor items={[buildItem()]} message={message} />);

    expect(
      screen.queryByRole('button', {
        name: (_, element) => element.getAttribute('data-tooltip-content') === 'navigation.show_child_items',
      })
    ).toBeNull();
  });

  it('折りたたみボタンをクリックすると子要素が非表示になり、再クリックで再表示される', async () => {
    const user = userEvent.setup();
    const parent = buildItem({ id: 1, uuid: 'parent' });
    const child = buildItem({ id: 2, uuid: 'child', parent: 1 });
    render(<NavigationEditor items={[parent, child]} message={message} />);

    const collapseButton = screen.getByRole('button', {
      name: (_, element) => element.getAttribute('data-tooltip-content') === 'navigation.show_child_items',
    });
    expect(collapseButton).toHaveAttribute('aria-expanded', 'true');
    expect(screen.getAllByRole('textbox', { name: message.label })).toHaveLength(2);

    await user.click(collapseButton);

    expect(collapseButton).toHaveAttribute('aria-expanded', 'false');
    expect(screen.getAllByRole('textbox', { name: message.label })).toHaveLength(1);

    await user.click(collapseButton);

    expect(collapseButton).toHaveAttribute('aria-expanded', 'true');
    expect(screen.getAllByRole('textbox', { name: message.label })).toHaveLength(2);
  });

  it('全て表示/全て非表示ボタンが acms-admin-btn acms-admin-float-right を維持しつつ表示切替する', async () => {
    const user = userEvent.setup();
    const { container } = render(<NavigationEditor items={[buildItem()]} message={message} />);

    const showAllButton = within(container).getByRole('button', { name: 'navigation.show_all_details' });
    expect(showAllButton).toHaveClass('acms-admin-btn', 'acms-admin-float-right');
    expect(showAllButton).toHaveAttribute('aria-pressed', 'false');

    await user.click(showAllButton);

    const hideAllButton = within(container).getByRole('button', { name: 'navigation.hide_all_details' });
    expect(hideAllButton).toHaveClass('acms-admin-btn', 'acms-admin-float-right');
    expect(hideAllButton).toHaveAttribute('aria-pressed', 'true');
  });
});
