/**
 * (metadata, happy detail path, negative parse → notFound).
 */
import React from 'react'
import { render, screen } from '@testing-library/react'
import { APPLICATION_LIST_INITIAL_PAGE_SIZE } from '@/constants/application'

jest.mock('next-intl/server', () => ({
  getTranslations: (ns: string) =>
    Promise.resolve((key: string) => `${ns}.${key}`),
}))

const mockNotFound = jest.fn(() => {
  const err = new Error('NEXT_NOT_FOUND')
  ;(err as unknown as { digest?: string }).digest = 'NEXT_NOT_FOUND'
  throw err
})

jest.mock('next/navigation', () => ({
  notFound: () => mockNotFound(),
}))

jest.mock('@/util/filter', () => ({
  parseFilterSearchParams: jest.fn(),
}))

jest.mock('@/components/api-product/detail', () => ({
  __esModule: true,
  default: ({
    id,
    inlinetoasttype,
    inlinetoastmsgkey,
  }: {
    id: string
    inlinetoasttype: string
    inlinetoastmsgkey: string
  }) => (
    <div
      data-testid="detail-wrapper"
      data-inline-type={inlinetoasttype}
      data-inline-key={inlinetoastmsgkey}
    >
      {`ApiProductDetailWrapper:${id}`}
    </div>
  ),
}))

jest.mock('@/providers/filter-provider', () => ({
  FilterProvider: ({
    filter,
    children,
  }: {
    filter: unknown
    children: React.ReactNode
  }) => (
    <div data-testid="filter-provider" data-filter={JSON.stringify(filter)}>
      {children}
    </div>
  ),
}))

describe('[locale]/(end-user)/api-products/[id]/page.tsx', () => {
  const { parseFilterSearchParams } = jest.requireMock('@/util/filter') as {
    parseFilterSearchParams: jest.Mock
  }

  beforeEach(() => {
    jest.clearAllMocks()
    parseFilterSearchParams.mockReset()
  })

  describe('generateMetadata', () => {
    it('uses layout namespace for title/description', async () => {
      const { generateMetadata } = await import('../page')
      const metadata = await generateMetadata()
      expect(metadata.title).toBe('layout.header.apiproducts')
      expect(metadata.description).toBe('')
    })
  })

  describe('negative — filter parse fails', () => {
    it('delegates to notFound and stops before wrapper', async () => {
      parseFilterSearchParams.mockReturnValue({
        error: new Error('parse'),
        data: null,
      })
      const { default: ApiProductDetailPage } = await import('../page')

      await expect(
        ApiProductDetailPage({
          params: Promise.resolve({ id: '123' }),
          searchParams: Promise.resolve({}),
        })
      ).rejects.toThrow('NEXT_NOT_FOUND')

      expect(mockNotFound).toHaveBeenCalledTimes(1)
    })
  })

  describe('happy path', () => {
    beforeEach(() => {
      parseFilterSearchParams.mockReturnValue({
        error: null,
        data: { page: 1, limit: 8 },
      })
    })

    it('parses merged limit with APPLICATION_LIST_INITIAL_PAGE_SIZE fallback', async () => {
      const { default: ApiProductDetailPage } = await import('../page')

      await ApiProductDetailPage({
        params: Promise.resolve({ id: 'xyz' }),
        searchParams: Promise.resolve({}),
      })

      expect(parseFilterSearchParams).toHaveBeenCalledWith({
        limit: APPLICATION_LIST_INITIAL_PAGE_SIZE,
      })
    })

    it('renders ApiProductDetailWrapper + passes inline toast props', async () => {
      const { default: ApiProductDetailPage } = await import('../page')

      const element = await ApiProductDetailPage({
        params: Promise.resolve({ id: 'prod-99' }),
        searchParams: Promise.resolve({
          inlinetoasttype: 'warn',
          inlinetoastmsgkey: 'KEY',
          page: '1',
        }),
      })

      render(element as React.ReactElement)

      const w = screen.getByTestId('detail-wrapper')
      expect(w).toHaveTextContent('ApiProductDetailWrapper:prod-99')
      expect(w).toHaveAttribute('data-inline-type', 'warn')
      expect(w).toHaveAttribute('data-inline-key', 'KEY')
      expect(screen.getByTestId('filter-provider')).toBeInTheDocument()
    })
  })
})
