import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { renderToString } from 'react-dom/server';
import { Accordion as AccordionController } from '@42/core/accordion';
import { Accordion } from './components/Accordion';

/**
 * SSR-safety: `useC42` defers all DOM work to `useEffect`, which never runs on
 * the server. Rendering an adapter component with `react-dom/server` must:
 *   1. not throw,
 *   2. never construct the controller (no DOM access), and
 *   3. produce static markup without any of the controller's runtime mutations
 *      (ARIA attributes, `data-state`, wrapped panel content).
 */
describe('react-dom/server SSR safety', () => {
  beforeEach(() => {
    // Reset jsdom DOM so we can assert the render touched nothing.
    document.body.innerHTML = '';
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('does not construct the controller during server render', () => {
    const ctor = vi.spyOn(AccordionController.prototype, 'destroy');

    let html = '';
    expect(() => {
      html = renderToString(
        <Accordion>
          <div data-c42-accordion-item data-value="a">
            <button data-c42-accordion-trigger>A</button>
            <div data-c42-accordion-panel>Panel A</div>
          </div>
        </Accordion>,
      );
    }).not.toThrow();

    // Static markup is present...
    expect(html).toContain('data-c42-accordion');
    expect(html).toContain('data-c42-accordion-trigger');

    // ...but none of the controller's runtime DOM mutations are.
    expect(html).not.toContain('aria-expanded');
    expect(html).not.toContain('data-state');
    expect(html).not.toContain('data-c42-accordion-panel-content');

    // The controller's lifecycle never ran (destroy belongs to a live instance).
    expect(ctor).not.toHaveBeenCalled();
  });

  it('does not touch the document while rendering on the server', () => {
    expect(document.body.childElementCount).toBe(0);

    renderToString(
      <Accordion>
        <div data-c42-accordion-item data-value="a">
          <button data-c42-accordion-trigger>A</button>
          <div data-c42-accordion-panel>Panel A</div>
        </div>
      </Accordion>,
    );

    // renderToString returns a string; it must not mount anything into the DOM.
    expect(document.body.childElementCount).toBe(0);
  });
});
