/**
 * Blog theme — §4.3 post override functional-contract + sanitization floor gates.
 * Run under the render vitest project (AstroContainer harness via body-component-render).
 */
import { describe, expect, it } from 'vitest';
import BlogPostBody from './BlogPostBody.astro';
import { renderBodyComponent } from '../../test/body-component-render';

const PROSE_SNIPPET = '<p>Blog contract prose body</p>';
const POST_XSS = '<script>alert("xss-post")</script>';
const COMMENT_XSS = '<script>alert("xss-comment")</script>';
const MEDIA_URL = 'https://example.com/image.jpg';

const BASE_PROPS = {
  post: { id: 'blog-post-1', title: 'Blog layout test', body: PROSE_SNIPPET + POST_XSS },
  comments: [
    {
      author: { name: 'Test Reader' },
      depth: 0,
      createdAt: '2026-06-30T12:00:00.000Z',
      bodyHtml: '<p>Blog contract comment body</p>' + COMMENT_XSS,
    },
  ],
  commentTotal: 1,
  fields: [
    { key: 'featured_image', label: 'Featured image', type: 'media', value: { url: MEDIA_URL } },
  ],
};

describe('BlogPostBody', () => {
  it('renders post body prose and strips injected <script>', async () => {
    const html = await renderBodyComponent(BlogPostBody, BASE_PROPS);
    expect(html).toContain('Blog contract prose body');
    expect(html).not.toContain('alert("xss-post")');
  });

  it('sanitizes comment bodyHtml — strips injected <script>', async () => {
    const html = await renderBodyComponent(BlogPostBody, BASE_PROPS);
    expect(html).toContain('Blog contract comment body');
    expect(html).not.toContain('alert("xss-comment")');
  });

  it('renders media field as sanitized img markup', async () => {
    const html = await renderBodyComponent(BlogPostBody, BASE_PROPS);
    expect(html).toContain('<img');
    expect(html).toContain(MEDIA_URL);
  });

  it('strips hostile javascript: URL from media field', async () => {
    const html = await renderBodyComponent(BlogPostBody, {
      ...BASE_PROPS,
      fields: [
        { key: 'hostile', label: 'Hostile', type: 'media', value: { url: 'javascript:alert(1)' } },
      ],
    });
    expect(html).toContain('Hostile');
    expect(html).not.toContain('javascript:');
  });

  it('renders singular comment count label', async () => {
    const html = await renderBodyComponent(BlogPostBody, BASE_PROPS);
    expect(html).toContain('1 comment');
  });

  it('renders plural comment count label', async () => {
    const html = await renderBodyComponent(BlogPostBody, {
      ...BASE_PROPS,
      commentTotal: 2,
    });
    expect(html).toContain('2 comments');
  });

  it('renders empty-state when comments is empty', async () => {
    const html = await renderBodyComponent(BlogPostBody, {
      post: { id: 'blog-post-2', title: 'Empty state test', body: PROSE_SNIPPET },
      comments: [],
      commentTotal: 0,
      fields: [],
    });
    expect(html).toContain('Be the first to comment.');
  });

  it('renders back link', async () => {
    const html = await renderBodyComponent(BlogPostBody, BASE_PROPS);
    expect(html).toContain('class="blog-post__back"');
    expect(html).toContain('← Back to posts');
  });
});
