/**
 *  (happy path, contract).
 * RootLayout returns <html>; assert the React tree (avoids invalid DOM nesting + RSC markup issues).
 */
import React, { Children, isValidElement } from 'react'
import { describe, it, expect } from '@jest/globals'

function propsOf(el: unknown): Record<string, unknown> | null {
  if (!isValidElement(el)) return null
  return el.props as Record<string, unknown>
}

type HtmlProps = { lang?: string; children: React.ReactNode }
type BodyProps = { children?: React.ReactNode }

describe('app/layout.tsx — RootLayout', () => {
  it('happy path: nests children inside body', async () => {
    const { default: RootLayout } = await import('../layout')

    const tree = await RootLayout({
      children: <div>Root children</div>,
    })

    expect(isValidElement(tree)).toBe(true)
    const html = tree as React.ReactElement<HtmlProps>
    expect(html.type).toBe('html')

    const body = html.props.children
    expect(isValidElement(body) && body.type).toBe('body')

    const bodyEl = body as React.ReactElement<BodyProps>
    const inner = Children.toArray(bodyEl.props.children)
    expect(
      inner.some((c) => {
        if (!isValidElement<{ children?: React.ReactNode }>(c)) return false
        return c.type === 'div' && c.props.children === 'Root children'
      })
    ).toBe(true)
  })

  it('contract: html lang="en" and /env.js script', async () => {
    const { default: RootLayout } = await import('../layout')

    const tree = await RootLayout({
      children: <span>x</span>,
    })

    const html = tree as React.ReactElement<HtmlProps>
    expect(html.props.lang).toBe('en')

    const bodyEl = html.props.children as React.ReactElement<BodyProps>
    const inner = Children.toArray(bodyEl.props.children ?? null)

    expect(
      inner.some((c) => {
        const p = propsOf(c)
        return p !== null && p.src === '/env.js'
      })
    ).toBe(true)

    expect(
      inner.some((c) => {
        if (!isValidElement<{ children?: React.ReactNode }>(c)) return false
        return c.type === 'span' && c.props.children === 'x'
      })
    ).toBe(true)
  })

  it('negative: accepts null children without throwing', async () => {
    const { default: RootLayout } = await import('../layout')

    const tree = await RootLayout({ children: null })

    const html = tree as React.ReactElement<HtmlProps>
    expect(html.type).toBe('html')
    const bodyEl = html.props.children as React.ReactElement<BodyProps>
    const inner = Children.toArray(bodyEl.props.children ?? null)
    expect(
      inner.some((c) => {
        const p = propsOf(c)
        return p !== null && p.src === '/env.js'
      })
    ).toBe(true)
  })
})
