import { describe, test, expect } from 'vitest';
import React from 'react';
import { renderEditorHarness } from '../../test-utils/editorHarness';
import { EditorConfigProvider } from '../../state/EditorConfigContext';
import { PageProvider, usePages } from '../../state/PageContext';
import { SiteDesignProvider, useSiteDesign, DEFAULT_SITE_DESIGN } from '../../state/SiteDesignContext';
import { SiteDesignPanel } from './SiteDesignPanel';

/** React tracks a controlled `<input>`'s value via a wrapped native setter --
 *  a plain `input.value = x` assignment doesn't go through it, so React never
 *  sees the change and skips onChange. */
function setInputValue(input: HTMLInputElement, value: string) {
  const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')!.set!;
  setter.call(input, value);
  input.dispatchEvent(new Event('input', { bubbles: true }));
}

/**
 * Real-provider integration test -- NO mocks. Exercises the actual
 * `replaceAllPages`/`setHeader`/`setFooter`/`resetToDefaults` implementations,
 * which route the component's blank trees through the real
 * `treeToCraftState` -> `sanitizeAiTree`/`flattenTreeForCraft` pipeline (see
 * `state/PageContext.tsx` and `utils/craft-tree.ts`). This is the check the
 * task brief calls out specifically: a tree shape that fails sanitisation
 * would silently fall back to an empty canvas (masking a bug) rather than
 * throwing, so asserting only on mock call arguments (as
 * `SiteDesignPanel.reset.test.tsx` does) would not catch a bad tree shape --
 * the mocked assertions there only prove the component PASSED a
 * `{type:{resolvedName:'Container'}, nodes:[]}`-shaped object; they can't
 * prove that object is actually valid input to the real pipeline.
 */
describe('Reset Entire Site -- real PageContext/SiteDesignContext integration', () => {
  test('confirming produces a real, valid single blank Home page + header + footer + default design', () => {
    let pageCtx: ReturnType<typeof usePages> | null = null;
    let designCtx: ReturnType<typeof useSiteDesign> | null = null;
    const Probe: React.FC = () => {
      pageCtx = usePages();
      designCtx = useSiteDesign();
      return null;
    };

    const harness = renderEditorHarness();
    harness.mountChild(
      <EditorConfigProvider config={{
        user: 'u', apiUrl: '/api', csrfToken: 't', siteId: 1,
        siteDomain: 'example.com', siteName: 'Example', backUrl: '/', isRoot: false,
      }}>
        <PageProvider>
          <SiteDesignProvider>
            <Probe />
            <SiteDesignPanel />
          </SiteDesignProvider>
        </PageProvider>
      </EditorConfigProvider>,
    );

    // Dirty the design tokens first so resetToDefaults has something to undo.
    harness.act(() => { designCtx!.updateDesign({ primaryColor: '#000000' }); });
    expect(designCtx!.design.primaryColor).toBe('#000000');

    harness.act(() => {
      (harness.container.querySelector('[data-action="open-site-reset"]') as HTMLButtonElement).click();
    });
    const input = harness.container.querySelector('[data-testid="site-reset-domain"]') as HTMLInputElement;
    harness.act(() => { setInputValue(input, 'example.com'); });
    harness.act(() => {
      (harness.container.querySelector('[data-action="confirm-site-reset"]') as HTMLButtonElement).click();
    });

    // Exactly one page, "Home", landing-page slug -- and its stored
    // craftState is real, parseable Craft.js state with a Container ROOT
    // and no children (i.e. sanitizeAiTree did NOT reject the tree and fall
    // back to a silent empty canvas for the wrong reason -- it's genuinely
    // ROOT with zero nodes because that's what we asked for).
    expect(pageCtx!.pages).toHaveLength(1);
    expect(pageCtx!.pages[0].name).toBe('Home');
    expect(pageCtx!.pages[0].slug).toBe('index');
    const homeState = JSON.parse(pageCtx!.pages[0].craftState!);
    expect(homeState.ROOT.type.resolvedName).toBe('Container');
    expect(homeState.ROOT.nodes).toEqual([]);

    const headerState = JSON.parse(pageCtx!.headerPage.craftState!);
    expect(headerState.ROOT.type.resolvedName).toBe('Container');
    expect(headerState.ROOT.nodes).toEqual([]);
    expect(headerState.ROOT.props.tag).toBe('header');

    const footerState = JSON.parse(pageCtx!.footerPage.craftState!);
    expect(footerState.ROOT.type.resolvedName).toBe('Container');
    expect(footerState.ROOT.nodes).toEqual([]);
    expect(footerState.ROOT.props.tag).toBe('footer');

    // Design tokens are back to the defaults.
    expect(designCtx!.design).toEqual(DEFAULT_SITE_DESIGN);

    harness.unmount();
  });
});
