import { useEffect } from 'react'

const VISITOR_STORAGE_KEY = 'academy.analytics.visitor-id'
const VISITOR_COOKIE_NAME = 'academy_visitor_id'
const ONCE_PREFIX = 'academy.analytics.once:'

function getCsrfToken() {
  if (typeof document === 'undefined') {
    return ''
  }

  return document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
}

function getCookieValue(name) {
  if (typeof document === 'undefined') {
    return ''
  }

  const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`))
  return match ? decodeURIComponent(match[1]) : ''
}

function generateVisitorId() {
  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
    return crypto.randomUUID()
  }

  return `academy-${Date.now()}-${Math.random().toString(16).slice(2)}`
}

function ensureVisitorId() {
  if (typeof window === 'undefined') {
    return null
  }

  let visitorId = ''

  try {
    visitorId = window.localStorage.getItem(VISITOR_STORAGE_KEY) || ''
  } catch {
    visitorId = ''
  }

  if (!visitorId) {
    visitorId = getCookieValue(VISITOR_COOKIE_NAME)
  }

  if (!visitorId) {
    visitorId = generateVisitorId()
  }

  try {
    window.localStorage.setItem(VISITOR_STORAGE_KEY, visitorId)
  } catch {
    // Ignore storage failures and continue.
  }

  if (typeof document !== 'undefined') {
    document.cookie = `${VISITOR_COOKIE_NAME}=${encodeURIComponent(visitorId)}; path=/; max-age=31536000; SameSite=Lax`
  }

  return visitorId
}

function buildPayload(payload = {}) {
  return {
    ...payload,
    visitor_id: payload.visitor_id || ensureVisitorId(),
    url: payload.url || (typeof window !== 'undefined' ? window.location.href : null),
    _token: payload._token || getCsrfToken(),
  }
}

function markOnce(onceKey) {
  if (!onceKey || typeof window === 'undefined') {
    return false
  }

  const storageKey = `${ONCE_PREFIX}${onceKey}`

  try {
    if (window.sessionStorage.getItem(storageKey)) {
      return true
    }

    window.sessionStorage.setItem(storageKey, '1')
  } catch {
    return false
  }

  return false
}

export async function postAcademyAction(url, payload = {}) {
  if (!url || typeof window === 'undefined') {
    return null
  }

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'X-CSRF-TOKEN': getCsrfToken(),
    },
    credentials: 'same-origin',
    body: JSON.stringify(buildPayload(payload)),
  }).catch(() => null)

  if (!response?.ok) {
    return null
  }

  const responseContentType = response.headers.get('content-type') || ''
  if (!responseContentType.includes('application/json')) {
    return null
  }

  return response.json().catch(() => null)
}

export function trackAcademyEvent(eventType, contentType, contentId, metadata = {}, options = {}) {
  if (!eventType || !options?.url || typeof window === 'undefined') {
    return Promise.resolve(false)
  }

  if (options.onceKey && markOnce(options.onceKey)) {
    return Promise.resolve(false)
  }

  const payload = buildPayload({
    event_type: eventType,
    content_type: contentType || null,
    content_id: contentId || null,
    metadata,
    route_name: options.pageName || null,
  })

  const body = JSON.stringify(payload)

  if (options.useBeacon !== false && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {
    try {
      const blob = new Blob([body], { type: 'application/json' })
      const queued = navigator.sendBeacon(options.url, blob)

      if (queued) {
        return Promise.resolve(true)
      }
    } catch {
      // Fall back to fetch.
    }
  }

  return fetch(options.url, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'X-CSRF-TOKEN': getCsrfToken(),
    },
    credentials: 'same-origin',
    keepalive: options.keepalive === true,
    body,
  }).then(() => true).catch(() => false)
}

export function normalizeAcademySearchQuery(query = '') {
  const normalizedWhitespace = String(query).trim().toLowerCase().replace(/\s+/g, ' ')
  return normalizedWhitespace.replace(/[^a-z0-9\s\-_]+/g, '').trim()
}

export function trackAcademySearchResultClick(analytics, search, result) {
  if (!analytics?.eventUrl || !search?.query || !result?.contentType || !result?.contentId) {
    return
  }

  void trackAcademyEvent('academy_search_result_click', result.contentType, result.contentId, {
    query: search.query,
    normalized_query: search.normalizedQuery || normalizeAcademySearchQuery(search.query),
    results_count: Number(search.resultsCount || 0),
    position: result.position || null,
    source: result.source || 'academy_search_results',
    filters: search.filters || {},
  }, {
    url: analytics.eventUrl,
    pageName: analytics.pageName,
    keepalive: true,
  })
}

function contentViewEventType(contentType) {
  if (contentType === 'academy_lesson') return 'academy_lesson_view'
  if (contentType === 'academy_course') return 'academy_course_view'
  if (contentType === 'academy_prompt_pack') return 'academy_prompt_pack_view'
  if (contentType === 'academy_challenge') return 'academy_challenge_view'
  return 'academy_content_view'
}

function analyticsMetadata(analytics, extra = {}) {
  const metadata = analytics?.metadata && typeof analytics.metadata === 'object' ? analytics.metadata : {}

  return {
    page_name: analytics?.pageName,
    ...metadata,
    ...extra,
  }
}

function analyticsTrackingKey(analytics) {
  if (analytics?.trackingKey) {
    return String(analytics.trackingKey)
  }

  const metadata = analytics?.metadata && typeof analytics.metadata === 'object' ? analytics.metadata : {}
  const pairs = Object.entries(metadata)
    .filter(([, value]) => value !== undefined && value !== null && value !== '')
    .sort(([left], [right]) => left.localeCompare(right))
    .map(([key, value]) => `${key}:${String(value)}`)

  return pairs.join('|')
}

export function trackUpgradeClick(analytics, metadata = {}) {
  if (!analytics?.eventUrl) {
    return
  }

  void trackAcademyEvent('academy_upgrade_click', analytics?.contentType || 'academy_upgrade', analytics?.contentId || null, metadata, {
    url: analytics.eventUrl,
    pageName: analytics.pageName,
    useBeacon: false,
  })
}

export function useAcademyPageAnalytics(analytics) {
  useEffect(() => {
    if (!analytics?.enabled || !analytics?.eventUrl || typeof window === 'undefined') {
      return undefined
    }

    const trackingKey = analyticsTrackingKey(analytics)
    const baseKey = `${analytics.pageName || window.location.pathname}:${analytics.contentType || 'page'}:${analytics.contentId || 'none'}:${trackingKey || 'default'}`

    void trackAcademyEvent('academy_page_view', analytics.contentType || null, analytics.contentId || null, analyticsMetadata(analytics), {
      url: analytics.eventUrl,
      pageName: analytics.pageName,
      onceKey: `${baseKey}:page-view`,
    })

    if (analytics.contentType || analytics.contentId) {
      void trackAcademyEvent(contentViewEventType(analytics.contentType), analytics.contentType || null, analytics.contentId || null, analyticsMetadata(analytics), {
        url: analytics.eventUrl,
        pageName: analytics.pageName,
        onceKey: `${baseKey}:content-view`,
      })
    }

    if (analytics.isPremium && analytics.isLocked) {
      void trackAcademyEvent('academy_premium_preview_view', analytics.contentType || null, analytics.contentId || null, analyticsMetadata(analytics), {
        url: analytics.eventUrl,
        pageName: analytics.pageName,
        onceKey: `${baseKey}:premium-preview`,
      })
    }

    const engagedTimer = window.setTimeout(() => {
      void trackAcademyEvent('academy_engaged_view', analytics.contentType || null, analytics.contentId || null, analyticsMetadata(analytics, {
        engaged_seconds: 15,
      }), {
        url: analytics.eventUrl,
        pageName: analytics.pageName,
        onceKey: `${baseKey}:engaged`,
      })
    }, 15000)

    const sentMilestones = new Set()

    const onScroll = () => {
      const doc = document.documentElement
      const scrollable = Math.max(1, doc.scrollHeight - window.innerHeight)
      const percent = Math.min(100, Math.round((window.scrollY / scrollable) * 100))

      ;[
        { threshold: 50, eventType: 'academy_scroll_50' },
        { threshold: 75, eventType: 'academy_scroll_75' },
        { threshold: 100, eventType: 'academy_scroll_100' },
      ].forEach((milestone) => {
        if (percent < milestone.threshold || sentMilestones.has(milestone.threshold)) {
          return
        }

        sentMilestones.add(milestone.threshold)
        void trackAcademyEvent(milestone.eventType, analytics.contentType || null, analytics.contentId || null, analyticsMetadata(analytics, {
          scroll_percent: milestone.threshold,
        }), {
          url: analytics.eventUrl,
          pageName: analytics.pageName,
          onceKey: `${baseKey}:scroll-${milestone.threshold}`,
        })
      })
    }

    window.addEventListener('scroll', onScroll, { passive: true })

    return () => {
      window.clearTimeout(engagedTimer)
      window.removeEventListener('scroll', onScroll)
    }
  }, [analytics?.contentId, analytics?.contentType, analytics?.enabled, analytics?.eventUrl, analytics?.isLocked, analytics?.isPremium, analytics?.pageName, analytics?.trackingKey, JSON.stringify(analytics?.metadata || {})])
}