/**
 * (navigation, thumbnail lifecycle, resource count i18n branch).
 */
import React from 'react'
import { act, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import type { GetApiProductResponse } from '@/services/api-product/apiProduct.schema'
import { ProductCard } from '../index'

const mockPush = jest.fn()
const mockCreateObjectURL = jest.fn(() => 'https://thumb.url')
const mockRevokeObjectURL = jest.fn()

beforeAll(() => {
  global.URL.createObjectURL = mockCreateObjectURL
  global.URL.revokeObjectURL = mockRevokeObjectURL
})

jest.mock('@/i18n/navigation', () => ({
  useRouter: () => ({ push: mockPush }),
}))
jest.mock('next-intl', () => ({
  useTranslations: () => (k: string, opts?: { count?: number }) =>
    opts?.count != null ? `${k}:${opts.count}` : k,
}))
const mockUseGetApiProductThumbnail = jest.fn()
jest.mock('@/services/api-product/apiProduct.query-options', () => ({
  useGetApiProductThumbnail: (id: string) => mockUseGetApiProductThumbnail(id),
}))
jest.mock('next/image', () => ({
  __esModule: true,
  default: (p: { alt: string; src?: string; onError?: () => void }) => (
    <img
      alt={p.alt}
      src={p.src}
      onError={p.onError}
      data-testid="product-img"
    />
  ),
}))
jest.mock('lucide-react', () => ({ Layers: () => <span>Layers</span> }))
jest.mock('@/share/ui/badge', () => ({
  Badge: ({ children }: { children: React.ReactNode }) => (
    <span>{children}</span>
  ),
}))
jest.mock('@/share/ui/card', () => ({
  Card: ({
    children,
    onClick,
  }: {
    children: React.ReactNode
    onClick?: () => void
  }) => (
    <div data-testid="card" onClick={onClick}>
      {children}
    </div>
  ),
  CardContent: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
}))

const defaultProduct: GetApiProductResponse = {
  id: '1',
  name: 'PayAPI',
  displayName: 'Payment API',
  description: 'Desc',
  context: '/v1',
  version: '1.0',
  type: 'APIPRODUCT',
  createdTime: null,
  provider: 'P',
  lifeCycleStatus: 'PUBLISHED',
  thumbnailUri: '',
  avgRating: '0',
  throttlingPolicies: [],
  advertiseInfo: {
    advertised: false,
    apiExternalProductionEndpoint: null,
    apiExternalSandboxEndpoint: null,
    originalDevPortalUrl: null,
    apiOwner: null,
    vendor: 'V',
  },
  businessInformation: {
    businessOwner: null,
    businessOwnerEmail: null,
    technicalOwner: null,
    technicalOwnerEmail: null,
  },
  isSubscriptionAvailable: true,
  monetizationLabel: '',
  gatewayType: '',
  gatewayVendor: '',
  additionalProperties: [],
  monetizedInfo: false,
  egress: false,
  subtype: '',
  resourceCount: 0,
  aboutDescription: '',
  aboutImage: '',
  bannerDescription: '',
  bannerImage: '',
}

const mkProduct = (
  overrides?: Partial<GetApiProductResponse>
): GetApiProductResponse => ({ ...defaultProduct, ...overrides })

describe('[components/api-product/card] ProductCard', () => {
  beforeEach(() => {
    mockPush.mockClear()
    mockCreateObjectURL.mockClear()
    mockRevokeObjectURL.mockClear()
    mockUseGetApiProductThumbnail.mockReturnValue({ data: null })
  })

  describe('happy path — layout', () => {
    it('renders card shell', () => {
      render(<ProductCard product={mkProduct({ id: '1' })} />)
      expect(screen.getByTestId('card')).toBeInTheDocument()
    })

    it('click routes to localized detail path template', async () => {
      render(<ProductCard product={mkProduct({ id: '99' })} />)
      await userEvent.click(screen.getByTestId('card'))
      expect(mockPush).toHaveBeenCalledTimes(1)
      expect(mockPush).toHaveBeenCalledWith('/api-products/99')
    })
  })

  describe('thumbnail blob', () => {
    it('shows image from object URL when query returns Blob; image onError stays mounted', () => {
      mockUseGetApiProductThumbnail.mockReturnValue({ data: new Blob() })
      render(<ProductCard product={mkProduct({ id: '2', name: 'X' })} />)
      const img = screen.getByTestId('product-img')
      expect(img).toHaveAttribute('src', 'https://thumb.url')
      expect(img).toHaveAttribute('alt', 'X')
      act(() => {
        img.dispatchEvent(new Event('error', { bubbles: true }))
      })
      expect(screen.getByTestId('card')).toBeInTheDocument()
    })

    it('does not render image when thumbnail query has no blob', () => {
      mockUseGetApiProductThumbnail.mockReturnValue({ data: null })
      render(
        <ProductCard
          product={mkProduct({
            id: '4',
            name: 'No assets',
            displayName: 'No Assets API',
            resourceCount: 0,
          })}
        />
      )
      expect(screen.queryByTestId('product-img')).not.toBeInTheDocument()
    })
  })

  describe('resource count (i18n)', () => {
    it.each([
      { resourceCount: 5, fragment: 'card.api_count:5' },
      { resourceCount: 0, fragment: 'card.api_count:0' },
    ])('$fragment badge text', ({ resourceCount, fragment }) => {
      render(
        <ProductCard product={mkProduct({ id: '3', resourceCount })} />
      )
      expect(screen.getByText(fragment)).toBeInTheDocument()
    })
  })
})
