/**
 * Magazine theme — §4.3 override functional-contract + §4.4 registry honesty gates.
 * Run under the render vitest project (AstroContainer + registry .astro imports).
 */
import { beforeAll, describe, expect, it } from 'vitest';
import reactRenderer from '@astrojs/react/server.js';
import { THEME_REGISTRY_META } from '../lib/theme.js';
import { findUnwiredOverrides } from '../lib/theme-contract.js';
import { MOD_CMS_THEMES } from './registry.js';

const PROSE_SNIPPET = '<p>Magazine contract prose body</p>';
const METADATA_LABEL = 'SEO description';
const METADATA_VALUE = 'Magazine metadata field value';

type Container = {
  renderToString: (
    component: unknown,
    options?: { props?: Record<string, unknown> },
  ) => Promise<string>;
};

let container: Container;
let renderMagazinePostBody: () => Promise<string>;

describe('magazine theme — registry honesty (§4.4)', () => {
  it('construction guard passes at import (meta keys === registry keys)', () => {
    const metaIds = THEME_REGISTRY_META.map((t) => t.id).sort();
    const keyIds = Object.keys(MOD_CMS_THEMES).sort();
    expect(metaIds).toEqual(keyIds);
  });

  it('magazine is registered with no unwired overrides', () => {
    const magazine = MOD_CMS_THEMES.magazine;
    expect(magazine).toBeDefined();
    expect(magazine.id).toBe('magazine');
    expect(magazine.name).toBe('Magazine');
    expect(findUnwiredOverrides(magazine)).toEqual([]);
    expect(magazine.overrides.post).toBeDefined();
  });

  it('every registered theme has no unwired overrides', () => {
    for (const theme of Object.values(MOD_CMS_THEMES)) {
      expect(findUnwiredOverrides(theme)).toEqual([]);
    }
  });
});

describe('magazine theme — post override functional-contract (§4.3)', () => {
  beforeAll(async () => {
    const { experimental_AstroContainer: AstroContainer } = await import('astro/container');
    const MagazinePostBody = (await import('./magazine/MagazinePostBody.astro')).default;
    const astroContainer = await AstroContainer.create();
    astroContainer.addServerRenderer({ renderer: reactRenderer });
    astroContainer.addClientRenderer({
      name: '@astrojs/react',
      entrypoint: '@astrojs/react/client.js',
    });
    container = astroContainer;

    renderMagazinePostBody = () =>
      container.renderToString(MagazinePostBody, {
        props: {
          post: { id: 'magazine-post-1', title: 'Magazine layout test', body: PROSE_SNIPPET },
          comments: [
            {
              author: { name: 'Reader One' },
              depth: 0,
              createdAt: '2026-06-18T12:00:00.000Z',
              bodyHtml: '<p>Magazine contract comment body</p>',
            },
          ],
          commentTotal: 1,
          fields: [
            { key: 'seo_description', label: METADATA_LABEL, type: 'text', value: METADATA_VALUE },
          ],
        },
      });
  });

  it('renders prose, metadata, and comments sub-regions', async () => {
    const html = await renderMagazinePostBody();

    // prose
    expect(html).toContain('class="magazine-post__body"');
    expect(html).toContain('Magazine contract prose body');

    // metadata
    expect(html).toContain('class="magazine-post__content-fields"');
    expect(html).toContain(METADATA_LABEL);
    expect(html).toContain(METADATA_VALUE);

    // comments
    expect(html).toContain('class="magazine-post__comments"');
    expect(html).toContain('1 comment');
    expect(html).toContain('Magazine contract comment body');
    expect(html).toContain('action="/api/comments"');
  });
});
