import { html, TemplateResult } from 'lit'
import { property } from 'lit/decorators.js'
import { Ref, createRef } from 'lit/directives/ref.js'
import { classMap } from 'lit/directives/class-map.js'
import { PktElement } from '@/base-elements/element'
import { cssUtils } from './datepicker-utils'
import { IDatepickerStrings } from './datepicker-types'
import '@/components/icon'

/**
 * Abstract base class for datepicker input components
 *
 * Consolidates shared properties, methods, and event dispatchers
 * used by all three datepicker input types (single, multiple, range).
 *
 * Subclasses must implement:
 * - `strings` property with component-specific defaults
 * - `render()` method with component-specific template
 */
export abstract class PktDatepickerBase extends PktElement {
  // Shared properties (9 identical across all sub-components)
  @property({ type: String })
  inputType: string = 'date'

  @property({ type: String })
  id: string = ''

  @property({ type: String })
  min?: string

  @property({ type: String })
  max?: string

  @property({ type: String })
  placeholder?: string

  @property({ type: Boolean })
  readonly: boolean = false

  @property({ type: Boolean })
  disabled: boolean = false

  @property({ type: Object })
  inputClasses: Record<string, boolean> = {}

  @property({ type: Object })
  internals?: ElementInternals

  // Abstract property - must be implemented by subclasses
  abstract strings: IDatepickerStrings

  // Shared refs
  inputRef: Ref<HTMLInputElement> = createRef()
  btnRef: Ref<HTMLButtonElement> = createRef()

  // Shared getters
  get inputElement(): HTMLInputElement | undefined {
    return this.inputRef.value
  }

  get buttonElement(): HTMLButtonElement | undefined {
    return this.btnRef.value
  }

  get isInputReadonly(): boolean {
    return this.readonly || this.inputType === 'text'
  }

  // Shared event dispatchers (protected so subclasses can use them)
  protected dispatchToggleCalendar(e: Event): void {
    if (this.readonly) return

    this.dispatchEvent(
      new CustomEvent('toggle-calendar', {
        detail: e,
        bubbles: true,
        composed: true,
      }),
    )
  }

  protected dispatchInput(e: Event): void {
    this.dispatchEvent(
      new CustomEvent('input-change', {
        detail: e,
        bubbles: true,
        composed: true,
      }),
    )
  }

  protected dispatchFocus(): void {
    this.dispatchEvent(
      new CustomEvent('input-focus', {
        bubbles: true,
        composed: true,
      }),
    )
  }

  protected dispatchBlur(e: FocusEvent): void {
    this.dispatchEvent(
      new CustomEvent('input-blur', {
        detail: e,
        bubbles: true,
        composed: true,
      }),
    )
  }

  protected dispatchChange(e: Event): void {
    this.dispatchEvent(
      new CustomEvent('input-changed', {
        detail: e,
        bubbles: true,
        composed: true,
      }),
    )
  }

  // Shared render helper for calendar button
  protected renderCalendarButton(): TemplateResult {
    return html`
      <button
        class="${classMap(cssUtils.getButtonClasses())}"
        type="button"
        @click=${(e: Event) => this.dispatchToggleCalendar(e)}
        @keydown=${(e: KeyboardEvent) => {
          const { key } = e
          if (key === 'Enter' || key === ' ' || key === 'Space') {
            e.preventDefault()
            this.dispatchToggleCalendar(e)
          }
        }}
        ?disabled=${this.disabled}
        ${this.btnRef}
      >
        <pkt-icon name="calendar"></pkt-icon>
        <span class="pkt-btn__text">${this.strings.calendar?.buttonAltText || 'Åpne kalender'}</span>
      </button>
    `
  }

  // Shared method - no shadow DOM
  createRenderRoot() {
    return this
  }

  // Abstract render method - must be implemented by subclasses
  abstract render(): TemplateResult
}
