import { describe, test, expect } from 'vitest';
import { ButtonLink } from './basic/ButtonLink';
import { Icon } from './basic/Icon';
import { SocialLinks } from './basic/SocialLinks';
import { Logo } from './basic/Logo';
import { Menu } from './basic/Menu';
import { Navbar } from './basic/Navbar';
import { ContentSlider } from './sections/ContentSlider';
import { FeaturesGrid } from './sections/FeaturesGrid';
import { PricingTable } from './sections/PricingTable';
import { ImageBlock } from './media/ImageBlock';
import { VideoBlock } from './media/VideoBlock';
import { Gallery } from './sections/Gallery';
import { BackgroundSection } from './layout/BackgroundSection';
import { HeroSimple } from './sections/HeroSimple';
import { CallToAction } from './sections/CallToAction';
import { MapEmbed } from './media/MapEmbed';
import { FormContainer } from './forms/FormContainer';

const XSS = 'javascript:alert(1)';
const QUOTE_BREAKOUT = 'x" onerror="alert(1)"';

function toHtmlOf(Component: any) {
  return Component.toHtml as (props: any, childrenHtml: string) => { html: string };
}

describe('A3: exported URLs are wrapped in safeUrl + escapeAttr', () => {
  test('ButtonLink href', () => {
    const html = toHtmlOf(ButtonLink)({ href: XSS, text: 'Go' }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(ButtonLink)({ href: QUOTE_BREAKOUT, text: 'Go' }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('Icon href (link), class is escaped but NOT safeUrl-filtered', () => {
    const html = toHtmlOf(Icon)({ link: XSS, icon: 'fa-star' }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(Icon)({ link: QUOTE_BREAKOUT, icon: 'fa-star' }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
    // class attribute is a CSS class, not a URL -- still escaped for attr safety
    const html3 = toHtmlOf(Icon)({ icon: 'fa-star" onerror="alert(1)' }, '').html;
    expect(html3).not.toContain('onerror="alert(1)"');
  });

  test('SocialLinks href', () => {
    const html = toHtmlOf(SocialLinks)({ links: [{ platform: 'facebook', url: XSS }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(SocialLinks)({ links: [{ platform: 'facebook', url: QUOTE_BREAKOUT }] }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('Logo href + image src', () => {
    const html = toHtmlOf(Logo)({ href: XSS, type: 'text', text: 'Site' }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(Logo)({ type: 'image', imageSrc: XSS }, '').html;
    expect(html2).not.toContain('javascript:');
    const html3 = toHtmlOf(Logo)({ type: 'image', imageSrc: QUOTE_BREAKOUT }, '').html;
    expect(html3).not.toContain('onerror="alert(1)"');
  });

  test('Menu link href', () => {
    const html = toHtmlOf(Menu)({ links: [{ text: 'x', href: XSS }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(Menu)({ links: [{ text: 'x', href: QUOTE_BREAKOUT }] }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('Navbar logo href, logo image src, link hrefs', () => {
    const html = toHtmlOf(Navbar)({ logoUrl: XSS, logoType: 'text', logoText: 'Site', links: [{ text: 'x', href: XSS }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(Navbar)({ logoType: 'image', logoImage: XSS }, '').html;
    expect(html2).not.toContain('javascript:');
    const html3 = toHtmlOf(Navbar)({ logoUrl: QUOTE_BREAKOUT, links: [{ text: 'x', href: QUOTE_BREAKOUT }] }, '').html;
    expect(html3).not.toContain('onerror="alert(1)"');
  });

  test('ContentSlider button href + slide image src (background url)', () => {
    const html = toHtmlOf(ContentSlider)({ slides: [{ buttonText: 'Go', buttonHref: XSS, imageSrc: '' }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(ContentSlider)({ slides: [{ imageSrc: XSS }] }, '').html;
    expect(html2).not.toContain('javascript:');
    const html3 = toHtmlOf(ContentSlider)({ slides: [{ buttonText: 'Go', buttonHref: QUOTE_BREAKOUT }] }, '').html;
    expect(html3).not.toContain('onerror="alert(1)"');
  });

  test('FeaturesGrid image src + button url', () => {
    const html = toHtmlOf(FeaturesGrid)({ features: [{ title: 't', description: 'd', image: XSS }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(FeaturesGrid)({ features: [{ title: 't', description: 'd', buttonText: 'Go', buttonUrl: XSS }] }, '').html;
    expect(html2).not.toContain('javascript:');
  });

  test('PricingTable button href', () => {
    const html = toHtmlOf(PricingTable)({ plans: [{ name: 'p', price: '$1', period: '/mo', features: [], buttonText: 'Buy', buttonHref: XSS }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(PricingTable)({ plans: [{ name: 'p', price: '$1', period: '/mo', features: [], buttonText: 'Buy', buttonHref: QUOTE_BREAKOUT }] }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('ImageBlock img src', () => {
    const html = toHtmlOf(ImageBlock)({ src: XSS }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(ImageBlock)({ src: QUOTE_BREAKOUT }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('VideoBlock direct-file src is safeUrl-filtered on final emitted src', () => {
    // matches the .mp4 extension sniff in detectVideoType but carries a javascript: scheme
    const html = toHtmlOf(VideoBlock)({ videoUrl: 'javascript:alert(1)//x.mp4' }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(VideoBlock)({ videoUrl: '"><script>alert(1)</script>.mp4' }, '').html;
    expect(html2).not.toContain('<script>alert(1)</script>');
  });

  test('VideoBlock youtube embed still works after safeUrl pass', () => {
    const html = toHtmlOf(VideoBlock)({ videoUrl: 'https://www.youtube.com/watch?v=abc123' }, '').html;
    expect(html).toContain('https://www.youtube.com/embed/abc123');
  });

  test('Gallery img src', () => {
    const html = toHtmlOf(Gallery)({ images: [{ src: XSS, alt: 'a' }] }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(Gallery)({ images: [{ src: QUOTE_BREAKOUT, alt: 'a' }] }, '').html;
    expect(html2).not.toContain('onerror="alert(1)"');
  });

  test('BackgroundSection bg image url()', () => {
    const html = toHtmlOf(BackgroundSection)({ bgImage: XSS }, '').html;
    expect(html).not.toContain('javascript:');
  });

  test('HeroSimple bg image url() and bg video src', () => {
    const html = toHtmlOf(HeroSimple)({ bgType: 'image', bgImage: XSS }, '').html;
    expect(html).not.toContain('javascript:');
    const html2 = toHtmlOf(HeroSimple)({ bgType: 'video', bgVideo: XSS }, '').html;
    expect(html2).not.toContain('javascript:');
    const html3 = toHtmlOf(HeroSimple)({ bgType: 'video', bgVideo: QUOTE_BREAKOUT }, '').html;
    expect(html3).not.toContain('onerror="alert(1)"');
  });

  test('CallToAction bg image url()', () => {
    const html = toHtmlOf(CallToAction)({ bgType: 'image', bgValue: XSS }, '').html;
    expect(html).not.toContain('javascript:');
  });

  test('MapEmbed iframe src (found beyond the brief-listed sites via grep sweep)', () => {
    const html = toHtmlOf(MapEmbed)({ address: 'New York, NY', zoom: 14 }, '').html;
    expect(html).toContain('maps.google.com');
    expect(html).not.toContain('javascript:');
  });

  test('FormContainer legacy form action is safeUrl-filtered (found via grep sweep)', () => {
    const html = toHtmlOf(FormContainer)({ action: XSS, method: 'GET' }, '').html;
    expect(html).not.toContain('javascript:');
    // non-relay legacy path (no recipientEmail) still works normally
    const html2 = toHtmlOf(FormContainer)({ action: '/legacy', method: 'POST' }, '').html;
    expect(html2).toContain('action="/legacy"');
  });
});
