import { flushPromises, mount } from '@vue/test-utils';

import { describe, expect, it } from 'vitest';

import MarkdownLiveEditor from './MarkdownLiveEditor.vue';

describe('markdown live editor DOM safety', () => {
  it('renders raw HTML as text and removes unsafe link navigation', async () => {
    const wrapper = mount(MarkdownLiveEditor, {
      attachTo: document.body,
      props: {
        modelValue: [
          '<img src="x" onerror="window.__skillXss = true">',
          '',
          '[unsafe](javascript:alert(1))',
        ].join('\n'),
      },
    });

    for (let index = 0; index < 6; index++) await flushPromises();

    expect(
      wrapper.element.querySelector('img[onerror], script, iframe'),
    ).toBeNull();
    expect(wrapper.text()).toContain('<img src="x"');
    expect(wrapper.element.querySelector('a[href^="javascript:"]')).toBeNull();

    wrapper.unmount();
  });

  it('keeps an ordinary tight list in the live editor without fidelity loss', async () => {
    const wrapper = mount(MarkdownLiveEditor, {
      attachTo: document.body,
      props: { modelValue: '- first\n- second' },
    });

    for (let index = 0; index < 6; index++) await flushPromises();

    expect(wrapper.emitted('fidelityLoss')).toBeUndefined();
    expect(wrapper.emitted('update:modelValue')).toBeUndefined();
    expect(wrapper.text()).toContain('first');
    expect(wrapper.text()).toContain('second');

    wrapper.unmount();
  });

  it('does not rewrite a loaded Skill instruction document', async () => {
    const source = [
      '# Instructions',
      '',
      'Use this skill to verify the complete Skill management workflow.',
      '',
      '## Expected result',
      '',
      '- Markdown renders while editing.',
      '- Scripts are displayed and edited without execution.',
      '- Assets can be previewed safely.',
    ].join('\n');
    const wrapper = mount(MarkdownLiveEditor, {
      attachTo: document.body,
      props: { modelValue: source },
    });

    for (let index = 0; index < 8; index++) await flushPromises();

    expect(wrapper.emitted('fidelityLoss')).toBeUndefined();
    expect(wrapper.emitted('update:modelValue')).toBeUndefined();
    wrapper.unmount();
  });

  it('renders a YAML frontmatter block as a read-only atom and preserves it on round-trip', async () => {
    const source = [
      '---',
      'name: research-skill',
      'description: Research helper for the team.',
      '---',
      '',
      '# Instructions',
      '',
      'Use this skill to look up references.',
    ].join('\n');
    const wrapper = mount(MarkdownLiveEditor, {
      attachTo: document.body,
      props: { modelValue: source },
    });

    for (let index = 0; index < 8; index++) await flushPromises();

    const frontmatterNode = wrapper.element.querySelector(
      '.milkdown-frontmatter',
    );
    expect(frontmatterNode).not.toBeNull();
    expect(wrapper.text()).toContain('Skill 元数据');
    expect(wrapper.text()).toContain('name: research-skill');
    expect(wrapper.text()).toContain('Use this skill');
    expect(frontmatterNode?.getAttribute('contenteditable')).toBe('false');
    expect(wrapper.emitted('fidelityLoss')).toBeUndefined();

    wrapper.unmount();
  });

  it('emits frontmatterActivate when the frontmatter block is clicked', async () => {
    const source = ['---', 'name: research-skill', '---', '', '# Body'].join(
      '\n',
    );
    const wrapper = mount(MarkdownLiveEditor, {
      attachTo: document.body,
      props: { modelValue: source },
    });

    for (let index = 0; index < 8; index++) await flushPromises();

    const frontmatterNode = wrapper.element.querySelector<HTMLElement>(
      '.milkdown-frontmatter',
    );
    expect(frontmatterNode).not.toBeNull();
    frontmatterNode?.click();

    expect(wrapper.emitted('frontmatterActivate')).toHaveLength(1);

    wrapper.unmount();
  });
});
