import $ from 'jquery'
import onFind from './dom/onFind'

const ANALYTICS_DATA_PATH =
  window.BRIGHTSPOT?.web?.pagePaths[
    'com.psddev.analytics.ui.AnalyticsDataToolPage'
  ]

interface AnalyticsData {
  periodLabel: string
  chartData: string
}

interface AnalyticsError {
  error: string
}

type AnalyticsResponse = AnalyticsData | AnalyticsError

export default class AnalyticsWidget {
  private readonly element: HTMLElement
  private readonly contentId: string
  private readonly analyticsUrl: string | undefined
  private isLoaded = false
  private cache: Record<string, AnalyticsData> = {}
  private currentPeriod = 'hours'

  private readonly loadingElement: HTMLElement | null
  private readonly contentElement: HTMLElement | null
  private readonly errorElement: HTMLElement | null
  private readonly periodSelector: HTMLSelectElement | null

  constructor(element: HTMLElement) {
    this.element = element
    this.contentId = element.dataset.contentId || ''
    this.analyticsUrl = ANALYTICS_DATA_PATH

    this.loadingElement = element.querySelector('.AnalyticsWidget-loading')
    this.contentElement = element.querySelector('.AnalyticsWidget-content')
    this.errorElement = element.querySelector('.AnalyticsWidget-error')
    this.periodSelector = element.querySelector(
      '.AnalyticsWidget-periodSelector',
    )

    this.init()
  }

  private init(): void {
    // Listen for tab activation
    $(this.element)
      .closest('[data-tab]')
      .on('tabbedShow', () => {
        // Only load if tab is actually selected/visible, not just during initial setup
        const tabElement = this.element.closest<HTMLElement>('[data-tab]')
        if (
          !this.isLoaded &&
          !tabElement?.classList.contains('TC-unselected')
        ) {
          this.loadAnalyticsData()
        }
      })

    // Listen for period selector changes
    if (this.periodSelector) {
      this.periodSelector.addEventListener('change', (e: Event) => {
        const target = e.target
        if (target !== null && target instanceof HTMLSelectElement) {
          this.currentPeriod = target.value
          this.loadAnalyticsData()
        }
      })
    }
  }

  private async loadAnalyticsData(): Promise<void> {
    const period = this.currentPeriod

    // Check cache first
    if (this.cache[period]) {
      this.displayData(this.cache[period])
      return
    }

    // Check if analytics URL is available
    if (!this.analyticsUrl) {
      console.error('Analytics data endpoint not found in pagePaths')
      this.showError()
      return
    }

    this.showLoading()

    try {
      const response = await fetch(
        `${this.analyticsUrl}?id=${this.contentId}&period=${period}`,
      )

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
      }

      const data: AnalyticsResponse = await response.json()

      if ('error' in data) {
        throw new Error(data.error)
      }

      // Cache the result
      this.cache[period] = data
      this.displayData(data)
      this.isLoaded = true
    } catch (error) {
      console.error('Failed to load analytics data:', error)
      this.showError()
    }
  }

  private showLoading(): void {
    if (this.loadingElement) this.loadingElement.hidden = false
    if (this.contentElement) this.contentElement.hidden = true
    if (this.errorElement) this.errorElement.hidden = true
  }

  private showError(): void {
    if (this.loadingElement) this.loadingElement.hidden = true
    if (this.contentElement) this.contentElement.hidden = true
    if (this.errorElement) this.errorElement.hidden = false
  }

  private displayData(data: AnalyticsData): void {
    if (this.loadingElement) this.loadingElement.hidden = true
    if (this.errorElement) this.errorElement.hidden = true
    if (this.contentElement) this.contentElement.hidden = false

    if (!this.contentElement) return

    // Clear previous content
    this.contentElement.innerHTML = ''

    // Create chart container with the period class for compatibility
    const chartContainer = document.createElement('div')
    chartContainer.className = `numbersPeriod numbersPeriod-${data.periodLabel}`
    chartContainer.addEventListener('highchart-loaded', () => {
      chartContainer.classList.add('chart-loaded')
    })

    // Insert the chart data (HTML from the server)
    if (data.chartData) {
      chartContainer.innerHTML = data.chartData
    }

    this.contentElement.appendChild(chartContainer)
  }
}

onFind('.AnalyticsWidget', (element: HTMLElement) => {
  new AnalyticsWidget(element)
})
