import { render, screen } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom'
import { describe, expect, it } from 'vitest'

import { DomainCard } from '../DomainCard'
import type { Listing } from '@/types/api'

/**
 * The browse-grid card.
 *
 * What is worth testing here is not the layout but the three places where the
 * card must not invent information: a listing with no price, an ownership
 * marker that is the whole proposition, and a registrar lock that has already
 * lapsed.
 */
function listing(overrides: Partial<Listing> = {}): Listing {
  return {
    id: '01HQZX000000000000000000',
    headline: 'coffee.com',
    description: 'A short, memorable name.',
    type: 'fixed_price',
    type_label: 'Fixed price',
    status: 'active',
    status_label: 'For sale',
    price: { minor: 1_250_000, currency: 'USD', amount: '12500.00', formatted: '$12,500.00' },
    accepts_offers: true,
    is_buy_now: true,
    is_featured: false,
    domain: {
      name: 'coffee.com',
      label: 'coffee',
      length: 6,
      tld: 'com',
      tld_display: '.com',
      is_premium_tld: true,
      has_hyphen: false,
      has_digit: false,
      ownership_verified: true,
      transfer_available_from: null,
      is_transfer_locked: false,
    },
    category: { slug: 'business', name: 'Business' },
    seller: {
      handle: 'himalaya-names',
      display_name: 'Himalaya Names',
      about: null,
      logo_url: null,
      tier: 'pro',
      tier_label: 'Pro seller',
      is_identity_verified: true,
      is_payment_verified: true,
      badges: [],
      rating_average: 4.8,
      rating_count: 19,
      completed_sales_count: 24,
      member_since: null,
    },
    views_count: 153,
    offers_count: 0,
    watchers_count: 2,
    published_at: '2026-07-01T00:00:00+00:00',
    ...overrides,
  }
}

function renderCard(value: Listing) {
  return render(
    <MemoryRouter>
      <DomainCard listing={value} />
    </MemoryRouter>,
  )
}

describe('DomainCard', () => {
  it('links to the detail page by domain name', () => {
    renderCard(listing())

    expect(screen.getByRole('link').getAttribute('href')).toBe('/domain/coffee.com')
  })

  it('shows the formatted price from the API rather than formatting it again', () => {
    renderCard(listing())

    expect(screen.getByText('$12,500.00')).toBeTruthy()
  })

  /**
   * The API sends null for a make-offer listing on purpose. Rendering a
   * formatted zero would misprice it, and a blank would look like a bug.
   */
  it('says "make an offer" instead of a price when there is none', () => {
    renderCard(
      listing({
        type: 'make_offer',
        type_label: 'Make offer',
        price: null,
        is_buy_now: false,
      }),
    )

    expect(screen.getByText('Make an offer')).toBeTruthy()
    expect(screen.queryByText('$0.00')).toBeNull()
  })

  it('marks a verified name as verified', () => {
    renderCard(listing())

    expect(screen.getByText('Ownership verified')).toBeTruthy()
  })

  /**
   * A lock that lifted months ago is not a constraint, and warning about it
   * would tell a buyer to expect a wait that does not exist.
   */
  it('does not advertise a transfer lock that has already lapsed', () => {
    const past = new Date(Date.now() - 86_400_000).toISOString()

    renderCard(
      listing({
        domain: {
          ...listing().domain,
          transfer_available_from: past,
          // The API decides this, not the client clock.
          is_transfer_locked: false,
        },
      }),
    )

    expect(screen.queryByText(/Transfer from/)).toBeNull()
  })

  it('states a transfer lock that is still in force', () => {
    const future = new Date(Date.now() + 30 * 86_400_000).toISOString()

    renderCard(
      listing({
        domain: {
          ...listing().domain,
          transfer_available_from: future,
          is_transfer_locked: true,
        },
      }),
    )

    expect(screen.getByText(/Transfer from/)).toBeTruthy()
  })

  it('surfaces an under-offer listing as still on the market', () => {
    renderCard(listing({ status: 'under_offer', status_label: 'Under offer' }))

    expect(screen.getByText('Under offer')).toBeTruthy()
  })
})
