import { PktElementWithSlot } from '@/base-elements/element-with-slot'
import { slotContent } from '@/directives/slot-content'
import { html, PropertyValues } from 'lit'
import { customElement, property, state } from 'lit/decorators.js'
import { provide } from '@lit/context'
import { tabsContext, type TabsContext } from './tabs-context'

export interface IPktTabs {
  arrowNav?: boolean
  disableArrowNav?: boolean
  separatorIconName?: string
  separatorIconPath?: string
}

export class PktTabs extends PktElementWithSlot<IPktTabs> implements IPktTabs {
  @property({ type: Boolean, reflect: true, attribute: 'arrow-nav' }) arrowNav: boolean = true
  @property({ type: Boolean, reflect: true, attribute: 'disable-arrow-nav' })
  disableArrowNav: boolean = false
  @property({ type: String, reflect: true, attribute: 'separator-icon-name' }) separatorIconName: string = ''
  @property({ type: String, reflect: true, attribute: 'separator-icon-path' }) separatorIconPath: string = ''

  @state() private tabRefs: Array<HTMLAnchorElement | HTMLButtonElement | null> = []
  @state() private disabledMap: Record<number, boolean> = {}
  @state() private tabCount: number = 0

  private get useArrowNav(): boolean {
    return this.arrowNav && !this.disableArrowNav
  }

  // Provide context to child tab items
  @provide({ context: tabsContext })
  @state()
  private context: TabsContext = {
    useArrowNav: this.useArrowNav,
    registerTab: this.registerTab.bind(this),
    handleClick: this.handleClick.bind(this),
    handleKeyUp: this.handleKeyUp.bind(this),
  }

  // Update context when properties change
  updated(changedProperties: PropertyValues) {
    if (changedProperties.has('arrowNav') || changedProperties.has('disableArrowNav')) {
      this.context = {
        ...this.context,
        useArrowNav: this.useArrowNav,
      }
    }
    this.updateComplete.then(() => this.syncSeparators())
  }

  private syncSeparators() {
    // Slotted tab items require post-render DOM sync for decorative separators.
    const list = this.querySelector('.pkt-tabs__list')
    if (!list) return

    list.querySelectorAll('.pkt-tabs__separator').forEach((separator) => separator.remove())
    const hasSeparator = !!(this.separatorIconName || this.separatorIconPath)
    if (!hasSeparator) return

    const items = Array.from(list.children).filter((child) => !child.classList.contains('pkt-tabs__separator'))
    for (let i = 0; i < items.length - 1; i++) {
      const separator = document.createElement('span')
      separator.className = 'pkt-tabs__separator'
      separator.setAttribute('aria-hidden', 'true')
      separator.setAttribute('role', 'presentation')

      if (this.separatorIconPath) {
        const img = document.createElement('img')
        img.setAttribute('src', this.separatorIconPath)
        img.setAttribute('alt', '')
        img.setAttribute('aria-hidden', 'true')
        separator.appendChild(img)
      } else if (this.separatorIconName) {
        const icon = document.createElement('pkt-icon')
        icon.setAttribute('name', this.separatorIconName)
        icon.classList.add('pkt-tabs__separator-icon')
        separator.appendChild(icon)
      }
      items[i].after(separator)
    }
  }

  private registerTab(element: HTMLElement, index: number, disabled = false) {
    this.tabRefs[index] = element as HTMLAnchorElement | HTMLButtonElement
    this.disabledMap[index] = disabled
    this.tabCount = Math.max(this.tabCount, index + 1)
  }

  private isTabDisabled(index: number): boolean {
    return !!this.disabledMap[index]
  }

  private findEnabledIndex(startIndex: number, direction: -1 | 1): number | null {
    let current = startIndex + direction

    while (current >= 0 && current < this.tabCount) {
      if (!this.isTabDisabled(current)) return current
      current += direction
    }

    return null
  }

  private handleClick(index: number) {
    if (this.isTabDisabled(index)) return

    this.dispatchEvent(
      new CustomEvent('tab-selected', {
        detail: { index },
        bubbles: true,
        composed: true,
      }),
    )
  }

  private handleKeyUp(keyEvent: KeyboardEvent, index: number) {
    if (!this.useArrowNav) return

    if (keyEvent.key === 'ArrowLeft') {
      keyEvent.preventDefault()
      const previousEnabled = this.findEnabledIndex(index, -1)
      if (previousEnabled !== null) this.tabRefs[previousEnabled]?.focus()
    }

    if (keyEvent.key === 'ArrowRight') {
      keyEvent.preventDefault()
      const nextEnabled = this.findEnabledIndex(index, 1)
      if (nextEnabled !== null) this.tabRefs[nextEnabled]?.focus()
    }

    if (
      keyEvent.key === 'Enter' ||
      keyEvent.key === ' ' ||
      keyEvent.key === 'Spacebar' ||
      keyEvent.key === 'ArrowDown'
    ) {
      keyEvent.preventDefault()
      this.handleClick(index)
    }
  }

  render() {
    const role = this.useArrowNav ? 'tablist' : 'navigation'
    const hasSeparator = !!(this.separatorIconName || this.separatorIconPath)
    const tabsClass = hasSeparator ? 'pkt-tabs pkt-tabs--with-separator' : 'pkt-tabs'

    return html`
      <div class=${tabsClass}>
        <div class="pkt-tabs__list" role=${role}>${slotContent(this)}</div>
      </div>
    `
  }
}

export default PktTabs

try {
  customElement('pkt-tabs')(PktTabs)
} catch (e) {
  console.warn('Forsøker å definere <pkt-tabs>, men den er allerede definert')
}
