import { describe, expect, it } from 'vitest'
import {
  buildBreadcrumbList,
  buildOrganization,
  buildWebSite,
  renderJsonLdScript,
  serializeJsonLd,
} from './jsonld.js'

const LS = '\u2028'
const PS = '\u2029'

describe('@platform-modules/seo/jsonld', () => {
  it('neutralizes the security-union XSS payload (escape-all beats partial subsets)', () => {
    const payload = {
      trap: `</script></SCRIPT>< /script<!--&${LS}${PS}`,
    }
    const out = serializeJsonLd(payload)

    expect(out).not.toContain('<')
    expect(out).not.toContain(LS)
    expect(out).not.toContain(PS)
    expect(out).toContain('\\u003c')
    expect(out).toContain('\\u0026')
    expect(out).toContain('\\u2028')
    expect(out).toContain('\\u2029')
  })

  it('buildBreadcrumbList emits schema.org BreadcrumbList', () => {
    const obj = buildBreadcrumbList([
      { name: 'Home', url: 'https://example.com/' },
      { name: 'Docs', url: 'https://example.com/docs' },
    ])
    expect(obj['@type']).toBe('BreadcrumbList')
    expect(obj.itemListElement).toHaveLength(2)
    expect((obj.itemListElement as { position: number }[])[1]?.position).toBe(2)
  })

  it('buildOrganization and buildWebSite emit valid schema.org objects', () => {
    const org = buildOrganization({ name: 'Acme', url: 'https://acme.test', logo: 'https://acme.test/logo.png' })
    expect(org['@type']).toBe('Organization')
    expect(org.logo).toBe('https://acme.test/logo.png')

    const site = buildWebSite({
      name: 'Acme',
      url: 'https://acme.test',
      searchUrlTemplate: 'https://acme.test/search?q={search_term_string}',
    })
    expect(site['@type']).toBe('WebSite')
    expect((site.potentialAction as { '@type': string })['@type']).toBe('SearchAction')
  })

  it('buildOrganization omits logo when absent', () => {
    const org = buildOrganization({ name: 'Acme', url: 'https://acme.test' })
    expect(org['@type']).toBe('Organization')
    expect('logo' in org).toBe(false)
  })

  it('buildWebSite omits potentialAction when searchUrlTemplate absent', () => {
    const site = buildWebSite({ name: 'Acme', url: 'https://acme.test' })
    expect(site['@type']).toBe('WebSite')
    expect('potentialAction' in site).toBe(false)
  })

  it('renderJsonLdScript wraps serialized output without a literal </script in the data region', () => {
    const html = renderJsonLdScript({ xss: '</script><script>alert(1)</script>' })
    expect(html.startsWith('<script type="application/ld+json">')).toBe(true)
    expect(html.endsWith('</script>')).toBe(true)
    const data = html.slice('<script type="application/ld+json">'.length, -'</script>'.length)
    expect(data).not.toContain('</script')
    expect(data).not.toContain('<')
  })
})
