// packages/commerce-catalog-react/src/ssr-seed.test.tsx
import { renderToStaticMarkup } from 'react-dom/server'
import { describe, expect, it, vi } from 'vitest'
import type { Page, Product } from '@platform-modules/commerce-catalog'
import { CatalogProvider } from './CatalogProvider.js'
import { useProductBySlug } from './useProductBySlug.js'
import { useProductList } from './useProductList.js'
import type { CatalogClient } from './client.js'

const prod = (slug: string, title: string): Product => ({
  id: 'p1', kind: 'physical', vendorId: null, slug, title, status: 'active',
  media: [], tags: [], createdAt: new Date(), updatedAt: new Date(), variants: [],
})

function mkClient(over: Partial<CatalogClient> = {}): CatalogClient {
  return {
    getProductBySlug: vi.fn(async () => null),
    getProductById: vi.fn(async () => null),
    listProducts: vi.fn(async () => ({ items: [], total: 0, page: 1, pageSize: 20 })),
    ...over,
  }
}

// Probes render ONLY the resolved content, so its presence in the SSR string IS the assertion.
function SlugProbe({ seed }: { seed?: Product }) {
  const { product } = useProductBySlug('tee', undefined, seed ? { initialData: seed } : undefined)
  return <span>{product ? product.title : 'LOADING'}</span>
}
function ListProbe({ seed }: { seed?: Page<Product> }) {
  const { page } = useProductList({ audience: 'public' }, seed ? { initialData: seed } : undefined)
  return <span>{page ? page.items.map((p) => p.title).join(',') : 'LOADING'}</span>
}

describe('SSR seed contract (§0) — seeded hooks render content into server HTML, zero fetch', () => {
  it('useProductBySlug seeded → title in renderToStaticMarkup output; client never called', () => {
    const client = mkClient()
    const html = renderToStaticMarkup(
      <CatalogProvider client={client}>
        <SlugProbe seed={prod('tee', 'Seeded Tee')} />
      </CatalogProvider>,
    )
    // BITE: under renderToStaticMarkup effects do NOT run. Seeded content reaches the HTML
    // ONLY via the useState initializer. Move the seed into a useEffect and this fails —
    // which is exactly the SSR regression the §0 contract forbids.
    expect(html).toContain('Seeded Tee')
    expect(client.getProductBySlug).not.toHaveBeenCalled()
  })

  it('useProductBySlug UNSEEDED → renders LOADING, no content, still no fetch (why §0 needs the seed)', () => {
    const client = mkClient()
    const html = renderToStaticMarkup(
      <CatalogProvider client={client}>
        <SlugProbe />
      </CatalogProvider>,
    )
    expect(html).toContain('LOADING')
    expect(html).not.toContain('Seeded Tee')
    expect(client.getProductBySlug).not.toHaveBeenCalled()
  })

  it('useProductList seeded → every item title in server HTML; client never called', () => {
    const client = mkClient()
    const seed: Page<Product> = {
      items: [prod('tee', 'Seeded Tee'), prod('mug', 'Seeded Mug')],
      total: 2, page: 1, pageSize: 20,
    }
    const html = renderToStaticMarkup(
      <CatalogProvider client={client}>
        <ListProbe seed={seed} />
      </CatalogProvider>,
    )
    expect(html).toContain('Seeded Tee')
    expect(html).toContain('Seeded Mug')
    expect(client.listProducts).not.toHaveBeenCalled()
  })
})
