import React from 'react'
import { cleanup, render, waitFor } from '@testing-library/react'

function prepareEnvironment() {
  document.head.innerHTML = '<meta name="csrf-token" content="csrf-token" />'
  const storage = new Map([['academy.analytics.visitor-id', 'visitor-123']])
  vi.spyOn(Storage.prototype, 'getItem').mockImplementation((key) => storage.get(String(key)) ?? null)
  vi.spyOn(Storage.prototype, 'setItem').mockImplementation((key, value) => {
    storage.set(String(key), String(value))
  })
  globalThis.fetch = vi.fn(() => Promise.resolve({ ok: true, headers: { get: () => 'application/json' }, json: () => Promise.resolve({ ok: true }) }))
}

function cleanupEnvironment() {
  cleanup()
  vi.restoreAllMocks()
  document.head.innerHTML = ''
}

test('academy search click attribution uses sendBeacon without blocking navigation', async () => {
  prepareEnvironment()

  const { trackAcademySearchResultClick } = await import('./academyAnalytics.js')

  Object.defineProperty(navigator, 'sendBeacon', {
    configurable: true,
    value: vi.fn(() => true),
  })

  const result = trackAcademySearchResultClick({
    eventUrl: '/academy/analytics/events',
    pageName: 'academy_prompts_index',
  }, {
    query: 'robot mascot',
    resultsCount: 12,
    filters: { difficulty: 'beginner' },
  }, {
    contentType: 'academy_prompt',
    contentId: 123,
    position: 3,
  })

  expect(result).toBeUndefined()
  expect(navigator.sendBeacon).toHaveBeenCalledTimes(1)
  expect(globalThis.fetch).not.toHaveBeenCalled()

  cleanupEnvironment()
})

test('academy search click attribution falls back to keepalive fetch when sendBeacon cannot queue', async () => {
  prepareEnvironment()

  const { trackAcademySearchResultClick } = await import('./academyAnalytics.js')

  Object.defineProperty(navigator, 'sendBeacon', {
    configurable: true,
    value: vi.fn(() => false),
  })

  trackAcademySearchResultClick({
    eventUrl: '/academy/analytics/events',
    pageName: 'academy_prompts_index',
  }, {
    query: 'robot mascot',
    resultsCount: 12,
    filters: { difficulty: 'beginner' },
  }, {
    contentType: 'academy_prompt',
    contentId: 123,
    position: 3,
  })

  expect(globalThis.fetch).toHaveBeenCalledTimes(1)
  expect(globalThis.fetch.mock.calls[0][1].keepalive).toBe(true)

  cleanupEnvironment()
})

test('academy page analytics includes custom metadata and varies page-view once keys by tracking context', async () => {
  prepareEnvironment()

  const { useAcademyPageAnalytics } = await import('./academyAnalytics.js')

  Object.defineProperty(navigator, 'sendBeacon', {
    configurable: true,
    value: undefined,
  })

  function TestPage({ analytics }) {
    useAcademyPageAnalytics(analytics)
    return React.createElement('div', null, 'Academy page')
  }

  const { rerender } = render(
    React.createElement(TestPage, {
      analytics: {
        enabled: true,
        eventUrl: '/academy/analytics/events',
        pageName: 'academy_prompts_popular',
        contentType: 'academy_prompt_popular',
        contentId: null,
        trackingKey: 'period:30d',
        metadata: { period: '30d', period_days: 30 },
      },
    }),
  )

  await waitFor(() => {
    expect(globalThis.fetch).toHaveBeenCalledTimes(2)
  })

  const firstPageView = globalThis.fetch.mock.calls
    .map((call) => JSON.parse(call[1].body))
    .find((payload) => payload.event_type === 'academy_page_view')

  expect(firstPageView.metadata.period).toBe('30d')
  expect(firstPageView.metadata.period_days).toBe(30)

  rerender(
    React.createElement(TestPage, {
      analytics: {
        enabled: true,
        eventUrl: '/academy/analytics/events',
        pageName: 'academy_prompts_popular',
        contentType: 'academy_prompt_popular',
        contentId: null,
        trackingKey: 'period:7d',
        metadata: { period: '7d', period_days: 7 },
      },
    }),
  )

  await waitFor(() => {
    expect(globalThis.fetch).toHaveBeenCalledTimes(4)
  })

  const pageViews = globalThis.fetch.mock.calls
    .map((call) => JSON.parse(call[1].body))
    .filter((payload) => payload.event_type === 'academy_page_view')

  expect(pageViews).toHaveLength(2)
  expect(pageViews[1].metadata.period).toBe('7d')

  cleanupEnvironment()
})