import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
import { waitFor } from '@testing-library/react';
import { fetchClient } from '@ablogcms/fetch-client';
import { useSettingsContext } from '@ablogcms/block-editor/editor-settings';
import { mountUnitInplaceEditorField, mountUnitInplaceEditorFromAttributes } from './mount-unit-inplace-editor';

vi.mock('@ablogcms/fetch-client', () => ({
  fetchClient: { get: vi.fn() },
}));

// BlockEditorSettingsProvider（コア側）が Context 経由で注入した EditorSettings を、
// inplace-editor 配下のコンポーネントが受け取れることを確認するためのスタブ。
vi.mock('@ablogcms/unit-editor/components/inplace-editor', () => ({
  default: ({ unitId }: { unitId: string }) => {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const settings = useSettingsContext();
    return (
      <div data-testid="inplace-editor-stub">
        <span data-testid="unit-id">{unitId}</span>
        <span data-testid="color-palette">{JSON.stringify(settings.colorPalette)}</span>
      </div>
    );
  },
}));

const getStub = () => document.querySelector('[data-testid="inplace-editor-stub"]');

describe('mountUnitInplaceEditorField / mountUnitInplaceEditorFromAttributes', () => {
  beforeEach(() => {
    vi.mocked(fetchClient.get).mockReset();
    vi.mocked(fetchClient.get).mockResolvedValue({
      data: { colorPalette: ['#00ffff'] },
      status: 200,
      statusText: 'OK',
      headers: new Headers(),
    });
    (window as unknown as { ACMS: { Config: Record<string, unknown>; Library: unknown } }).ACMS = {
      Config: { bid: 1, cid: 2 },
      Library: { acmsLink: vi.fn(() => 'ajax/edit/block-editor/settings.json') },
    };
  });

  afterEach(() => {
    document.body.innerHTML = '';
    vi.clearAllMocks();
  });

  it('mountUnitInplaceEditorField は unitId を InplaceEditor に渡し、EditorSettings が Context 経由で子孫に渡る', async () => {
    const target = document.createElement('div');
    document.body.appendChild(target);

    mountUnitInplaceEditorField(target, [] as never, {} as never, 'unit-1');

    await waitFor(() => {
      expect(getStub()).not.toBeNull();
    });
    expect(document.querySelector('[data-testid="unit-id"]')?.textContent).toBe('unit-1');
    await waitFor(() => {
      expect(document.querySelector('[data-testid="color-palette"]')?.textContent).toBe('["#00ffff"]');
    });
  });

  it('mountUnitInplaceEditorFromAttributes は element 自身をマウント先にし、unit-id / default-value を読む', async () => {
    const element = document.createElement('div');
    element.setAttribute('unit-id', 'unit-2');
    element.setAttribute('default-value', '[]');
    document.body.appendChild(element);

    mountUnitInplaceEditorFromAttributes(element);

    await waitFor(() => {
      expect(element.querySelector('[data-testid="inplace-editor-stub"]')).not.toBeNull();
    });
    expect(element.querySelector('[data-testid="unit-id"]')?.textContent).toBe('unit-2');
  });

  it('unit-id が無ければ空文字を渡す', async () => {
    const element = document.createElement('div');
    document.body.appendChild(element);

    mountUnitInplaceEditorFromAttributes(element);

    await waitFor(() => {
      expect(getStub()).not.toBeNull();
    });
    expect(document.querySelector('[data-testid="unit-id"]')?.textContent).toBe('');
  });

  it('unmount するとコンテナが空になる', async () => {
    const target = document.createElement('div');
    document.body.appendChild(target);

    const controller = mountUnitInplaceEditorField(target, [] as never, {} as never, 'unit-1');

    await waitFor(() => {
      expect(getStub()).not.toBeNull();
    });

    controller.unmount();

    expect(getStub()).toBeNull();
  });
});
