import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import { dialog } from '@ablogcms/dialog';
import AdminCard from './admin-card';
import type { AdminCardType } from '../../types';

vi.mock('@ablogcms/dialog', () => ({
  dialog: {
    confirm: vi.fn(),
    alert: vi.fn(),
  },
}));

// acms-admin-btn 系ボタンを Button コンポーネントに置き換えた際に、
// レンダリングされるクラス名・イベントハンドラの挙動が変わっていないことを保証する特徴付けテスト。

const baseCard: AdminCardType = {
  id: 'card-1',
  laneId: 'lane-1',
  title: 'サンプルタイトル',
  url: 'https://example.com',
  label: 'label',
  icon: 'acms-ico-star',
  index: 0,
};

const setup = (overrideCard: Partial<AdminCardType> = {}) => {
  const onDelete = vi.fn();
  const doneEdit = vi.fn();
  render(<AdminCard card={{ ...baseCard, ...overrideCard }} onDelete={onDelete} doneEdit={doneEdit} />);
  return { onDelete, doneEdit };
};

describe('AdminCard', () => {
  it('編集モードでない場合、編集ボタンが acms-admin-btn クラスで表示される', () => {
    setup();
    const editButton = screen.getByRole('button', { name: 'admin_menu.edit' });
    expect(editButton).toHaveClass('acms-admin-btn');
    expect(editButton).toHaveClass('acms-admin-menu-card-edit-btn');
  });

  it('編集ボタン押下で編集モードに入り、完了ボタンが acms-admin-btn クラスで表示される', () => {
    setup();
    fireEvent.click(screen.getByRole('button', { name: 'admin_menu.edit' }));
    const doneButton = screen.getByRole('button', { name: 'admin_menu.complete' });
    expect(doneButton).toHaveClass('acms-admin-btn');
    expect(doneButton).toHaveClass('acms-admin-float-right');
  });

  it('admin でない場合、削除ボタンが danger バリアントのクラスで表示され、押下で確認後に onDelete が呼ばれる', async () => {
    const { onDelete } = setup({ admin: false });
    fireEvent.click(screen.getByRole('button', { name: 'admin_menu.edit' }));
    const removeButton = screen.getByRole('button', { name: 'admin_menu.remove' });
    expect(removeButton).toHaveClass('acms-admin-btn');
    expect(removeButton).toHaveClass('acms-admin-btn-danger');
    expect(removeButton).toHaveClass('acms-admin-float-right');

    vi.mocked(dialog.confirm).mockResolvedValue(true);
    fireEvent.click(removeButton);
    await waitFor(() => expect(onDelete).toHaveBeenCalledTimes(1));
  });

  it('admin の場合、削除ボタンは表示されない', () => {
    setup({ admin: true });
    fireEvent.click(screen.getByRole('button', { name: 'admin_menu.edit' }));
    expect(screen.queryByRole('button', { name: 'admin_menu.remove' })).not.toBeInTheDocument();
  });

  it('完了ボタン押下で doneEdit が現在の入力内容付きで呼ばれる', () => {
    const { doneEdit } = setup({ admin: false });
    fireEvent.click(screen.getByRole('button', { name: 'admin_menu.edit' }));
    fireEvent.click(screen.getByRole('button', { name: 'admin_menu.complete' }));
    expect(doneEdit).toHaveBeenCalledWith(
      expect.objectContaining({
        id: 'card-1',
        laneId: 'lane-1',
        title: 'サンプルタイトル',
        url: 'https://example.com',
      })
    );
  });
});
