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 {
  getDefaultValue,
  getSettings,
  mountUnitConfigEditorField,
  mountUnitConfigEditorFromAttributes,
} from './mount-unit-config-editor';

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

vi.mock('@ablogcms/unit-editor/components/config-editor', () => ({
  default: ({ id, label }: { id: string; label: string }) => {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const settings = useSettingsContext();
    return (
      <div data-testid="unit-config-editor-stub">
        <span data-testid="id">{id}</span>
        <span data-testid="label">{label}</span>
        <span data-testid="color-palette">{JSON.stringify(settings.colorPalette)}</span>
      </div>
    );
  },
}));

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

describe('getDefaultValue', () => {
  it('default-value が無ければ空配列になる', () => {
    const element = document.createElement('div');
    expect(getDefaultValue(element)).toEqual([]);
  });

  it('default-value の JSON をパースする', () => {
    const element = document.createElement('div');
    element.setAttribute('default-value', '[{"id":"html","name":"自由入力"}]');
    expect(getDefaultValue(element)).toEqual([{ id: 'html', name: '自由入力' }]);
  });
});

describe('getSettings', () => {
  it('settings が無ければ既定値を使う', () => {
    const element = document.createElement('div');
    expect(getSettings(element)).toBeDefined();
  });

  it('settings の JSON を既定値にマージする', () => {
    const element = document.createElement('div');
    element.setAttribute('settings', '{"unitGroup":{"enable":false,"options":[]}}');
    expect(getSettings(element).unitGroup).toEqual({ enable: false, options: [] });
  });
});

describe('mountUnitConfigEditorField / mountUnitConfigEditorFromAttributes', () => {
  beforeEach(() => {
    vi.mocked(fetchClient.get).mockReset();
    vi.mocked(fetchClient.get).mockResolvedValue({
      data: { colorPalette: ['#ff00ff'] },
      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('id / label を UnitConfigEditor に渡し、EditorSettings が Context 経由で子孫に渡る', async () => {
    const target = document.createElement('div');
    document.body.appendChild(target);

    mountUnitConfigEditorField(target, 'config-1', '設定', [] as never, {} as never);

    await waitFor(() => {
      expect(getStub()).not.toBeNull();
    });
    expect(document.querySelector('[data-testid="id"]')?.textContent).toBe('config-1');
    expect(document.querySelector('[data-testid="label"]')?.textContent).toBe('設定');
    await waitFor(() => {
      expect(document.querySelector('[data-testid="color-palette"]')?.textContent).toBe('["#ff00ff"]');
    });
  });

  it('mountUnitConfigEditorFromAttributes は element 自身をマウント先にし、data-id / label を読む', async () => {
    const element = document.createElement('div');
    element.setAttribute('data-id', 'config-2');
    element.setAttribute('label', 'カスタム設定');
    element.setAttribute('default-value', '[]');
    document.body.appendChild(element);

    mountUnitConfigEditorFromAttributes(element);

    await waitFor(() => {
      expect(element.querySelector('[data-testid="unit-config-editor-stub"]')).not.toBeNull();
    });
    expect(element.querySelector('[data-testid="id"]')?.textContent).toBe('config-2');
    expect(element.querySelector('[data-testid="label"]')?.textContent).toBe('カスタム設定');
  });

  it('data-id が無ければ例外を投げる', () => {
    const element = document.createElement('div');
    expect(() => mountUnitConfigEditorFromAttributes(element)).toThrow('data-id is required');
  });

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

    const controller = mountUnitConfigEditorField(target, 'config-1', '設定', [] as never, {} as never);

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

    controller.unmount();

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