/**
 * Pagination component
 * @countermeasure/web-components/components/pagination
 */

export interface PaginationConfig {
  /** Container element (or selector) the controls are mounted into. */
  container: HTMLElement | string
  /**
   * Initial page number (1-based).
   * @default 1
   */
  page?: number
  /**
   * Whether further pages are available beyond the current one.
   * @default false
   */
  hasMore?: boolean
  /** Called whenever the user navigates to a different page. */
  onPageChange?: (page: number) => void
}

function resolveContainer(container: HTMLElement | string): HTMLElement {
  if (typeof container === 'string') {
    const el = document.querySelector(container)
    if (!el) {
      throw new Error(`Pagination: container not found for selector "${container}"`)
    }
    return el as HTMLElement
  }
  return container
}

export class Pagination {
  private readonly config: PaginationConfig
  private readonly containerEl: HTMLElement
  private readonly rootEl: HTMLElement
  private readonly prevBtn: HTMLButtonElement
  private readonly nextBtn: HTMLButtonElement
  private readonly infoEl: HTMLElement
  private currentPage: number
  private hasMore: boolean
  private destroyed = false

  constructor(config: PaginationConfig) {
    this.config = config
    this.containerEl = resolveContainer(config.container)
    this.currentPage = config.page ?? 1
    this.hasMore = config.hasMore === true

    this.rootEl = document.createElement('div')
    this.rootEl.className = 'cmm-pagination'

    this.prevBtn = document.createElement('button')
    this.prevBtn.className = 'cmm-pagination__button'
    this.prevBtn.textContent = 'Previous'
    this.prevBtn.addEventListener('click', this.handlePrev)

    this.infoEl = document.createElement('span')
    this.infoEl.className = 'cmm-pagination__info'

    this.nextBtn = document.createElement('button')
    this.nextBtn.className = 'cmm-pagination__button'
    this.nextBtn.textContent = 'Next'
    this.nextBtn.addEventListener('click', this.handleNext)

    this.rootEl.appendChild(this.prevBtn)
    this.rootEl.appendChild(this.infoEl)
    this.rootEl.appendChild(this.nextBtn)
    this.containerEl.appendChild(this.rootEl)

    this.render()
  }

  setPage(page: number, hasMore?: boolean): void {
    this.currentPage = page
    if (hasMore !== undefined) {
      this.hasMore = hasMore
    }
    this.render()
  }

  getPage(): number {
    return this.currentPage
  }

  destroy(): void {
    if (this.destroyed) {
      return
    }
    this.destroyed = true

    this.prevBtn.removeEventListener('click', this.handlePrev)
    this.nextBtn.removeEventListener('click', this.handleNext)

    if (this.rootEl.parentNode) {
      this.rootEl.parentNode.removeChild(this.rootEl)
    }
  }

  private render(): void {
    this.infoEl.textContent = `Page ${String(this.currentPage)}`

    if (this.currentPage <= 1) {
      this.prevBtn.disabled = true
      this.prevBtn.classList.add('cmm-pagination__button--disabled')
    } else {
      this.prevBtn.disabled = false
      this.prevBtn.classList.remove('cmm-pagination__button--disabled')
    }

    if (this.hasMore) {
      this.nextBtn.disabled = false
      this.nextBtn.classList.remove('cmm-pagination__button--disabled')
    } else {
      this.nextBtn.disabled = true
      this.nextBtn.classList.add('cmm-pagination__button--disabled')
    }
  }

  private readonly handlePrev = (): void => {
    if (this.currentPage > 1) {
      this.currentPage -= 1
      this.render()
      if (this.config.onPageChange) {
        this.config.onPageChange(this.currentPage)
      }
    }
  }

  private readonly handleNext = (): void => {
    if (this.hasMore) {
      this.currentPage += 1
      this.render()
      if (this.config.onPageChange) {
        this.config.onPageChange(this.currentPage)
      }
    }
  }
}
