export default class CraftAdminBarSearch extends HTMLElement {
  /**
   * The form element that handles the search.
   * @private
   */
  #searchForm: HTMLFormElement | null = null

  /**
   * The element that displays the search results
   * @private
   */
  #resultsElement: HTMLDivElement | null = null

  /**
   * Handles search via the Craft Search Admin Bar Widget
   * @private
   */
  private _onSearchFormSubmit = async (e: Event) => {
    e.preventDefault()
    const input: HTMLInputElement | null = this.#searchForm?.querySelector('input[type="search"]') ?? null

    if (input) {
      const response: {
        searchResults: { cpEditUrl: string; title: string; status: string; url: string }[]
        searchResultsStatus: 'OK' | 'NO_RESULTS'
      } = await window.adminBarPostRequest(
        this.closest('admin-bar'),
        'craft-search-search',
        JSON.stringify({ query: input.value })
      )

      if (this.#resultsElement) {
        let template
        let templateContent: DocumentFragment

        if (response.searchResultsStatus === 'OK') {
          template = document.getElementById('admin-bar-search-results-template') as HTMLTemplateElement
          templateContent = template.content

          const ulElement = document.createElement('ul')

          response.searchResults.forEach((entry) => {
            // Clone LI and styles from template
            const templateClone = templateContent.cloneNode(true) as HTMLElement
            const liElement = templateClone.querySelector('li')!

            // Link to the CP edit URL.
            const editButtonElement = liElement.querySelector('admin-bar-button.edit')!
            if (entry.cpEditUrl) {
              editButtonElement.setAttribute('button-href', entry.cpEditUrl)
              editButtonElement.setAttribute('label-text', entry.title)
            } else {
              liElement.removeChild(editButtonElement)
            }

            // If entry has a URL link to the page. If not, show the title as text.
            const viewButtonElement = liElement.querySelector('admin-bar-button.view')!
            const viewButtonTitleElement = viewButtonElement.querySelector('admin-bar-text')!
            const entryTitleElement = liElement.querySelector('admin-bar-text.view')!
            if (entry.url ?? false) {
              viewButtonElement.setAttribute('button-href', entry.url)
              viewButtonElement.setAttribute('badge-content', entry.status)
              viewButtonTitleElement.setAttribute('text-content', entry.title)
              entryTitleElement.remove()
            } else {
              entryTitleElement.setAttribute('text-content', entry.title)
              viewButtonElement.remove()
            }

            // Add all child elements to the search results
            ulElement.append(liElement)
          })

          this.#resultsElement.replaceChildren(ulElement)
        } else {
          template = document.getElementById('admin-bar-search-no-results-template') as HTMLTemplateElement
          templateContent = template.content

          this.#resultsElement.replaceChildren(templateContent.cloneNode(true))
        }
      }
    }
  }

  constructor() {
    super()

    const template = document.getElementById('admin-bar-search-template') as HTMLTemplateElement
    const templateContent = template.content

    const shadowRoot = this.attachShadow({ mode: 'open' })
    shadowRoot.appendChild(templateContent.cloneNode(true))

    this.#searchForm = this.shadowRoot?.querySelector('form') ?? null
    this.#resultsElement = this.shadowRoot?.querySelector('form + div') ?? null
  }

  connectedCallback(): void {
    // Set up search widget
    this.#searchForm?.addEventListener('submit', this._onSearchFormSubmit)
  }

  disconnectedCallback(): void {
    // Clean up search widget
    this.#searchForm?.removeEventListener('submit', this._onSearchFormSubmit)
  }
}

customElements.define('craft-admin-bar-search', CraftAdminBarSearch)
