import { PktElement } from '@/base-elements/element'
import { html, nothing } from 'lit'
import { customElement, property } from 'lit/decorators.js'
import { classMap } from 'lit/directives/class-map.js'
import {
  User,
  Representing,
  UserMenuItem,
  TInternalMenuItem,
  convertUserMenuItem,
  Booleanish,
  booleanishConverter,
} from './types'

import '@/components/icon'
import '@/components/link'

export interface IPktHeaderUserMenu {
  user: User
  formattedLastLoggedIn?: string
  representing?: Representing
  userMenu?: UserMenuItem[]
  canChangeRepresentation?: Booleanish
  logoutOnClick?: Booleanish
}

export class PktHeaderUserMenu
  extends PktElement<IPktHeaderUserMenu>
  implements IPktHeaderUserMenu
{
  @property({ type: Object }) user!: User
  @property({ type: String, attribute: 'formatted-last-logged-in' }) formattedLastLoggedIn?: string
  @property({ type: Object }) representing?: Representing
  @property({ type: Array, attribute: 'user-menu' }) userMenu?: UserMenuItem[]
  @property({
    type: Boolean,
    attribute: 'can-change-representation',
    converter: booleanishConverter,
  })
  canChangeRepresentation: Booleanish = false
  @property({ type: Boolean, attribute: 'logout-on-click', converter: booleanishConverter })
  logoutOnClick: Booleanish = false

  private handleChangeRepresentation() {
    this.dispatchEvent(
      new CustomEvent('change-representation', {
        bubbles: true,
        composed: true,
      }),
    )
  }

  private handleLogout() {
    this.dispatchEvent(
      new CustomEvent('log-out', {
        bubbles: true,
        composed: true,
      }),
    )
  }

  private handleMenuItemClick(item: TInternalMenuItem) {
    if ('onClick' in item && typeof item.onClick === 'function') {
      item.onClick()
    }
  }

  private renderLinkOrButton(item: TInternalMenuItem, className?: string) {
    const isLink = 'href' in item
    const classes = classMap({
      'pkt-user-menu__link': true,
      'pkt-link-button': !isLink,
      'pkt-link': !isLink,
      'pkt-link--icon-left': !isLink,
      [className || '']: !!className,
    })

    if (isLink) {
      return html`
        <pkt-link
          icon-name=${item.iconName || nothing}
          href=${item.href}
          aria-hidden="true"
          class="pkt-user-menu__link ${className || ''}"
        >
          ${item.title}
        </pkt-link>
      `
    }

    return html`
      <button class=${classes} type="button" @click=${() => this.handleMenuItemClick(item)}>
        ${item.iconName
          ? html`<pkt-icon
              name=${item.iconName}
              class="pkt-link__icon"
              aria-hidden="true"
            ></pkt-icon>`
          : nothing}
        ${item.title}
      </button>
    `
  }

  private renderLinkSection(links: TInternalMenuItem[]) {
    return html`
      <ul class="pkt-user-menu__sublist">
        ${links.map(
          (item) => html`
            <li class="pkt-user-menu__subitem">${this.renderLinkOrButton(item)}</li>
          `,
        )}
      </ul>
    `
  }

  render() {
    const internalMenuItems = this.userMenu?.map(convertUserMenuItem)

    return html`
      <nav class="pkt-user-menu" aria-label="Meny for innlogget bruker">
        <ul class="pkt-user-menu__list">
          <!-- User section -->
          ${this.user
            ? html`
                <li class="pkt-user-menu__item">
                  <div class="pkt-user-menu__label">Pålogget som</div>
                  <div class="pkt-user-menu__name" translate="no">${this.user.name}</div>
                  ${this.formattedLastLoggedIn
                    ? html`
                        <div class="pkt-user-menu__last-logged-in">
                          Sist pålogget: <time>${this.formattedLastLoggedIn}</time>
                        </div>
                      `
                    : nothing}
                </li>
              `
            : nothing}

          <!-- User menu items -->
          ${internalMenuItems && internalMenuItems.length > 0
            ? html`
                <li class="pkt-user-menu__item">${this.renderLinkSection(internalMenuItems)}</li>
              `
            : nothing}

          <!-- Representing section -->
          ${this.representing
            ? html`
                <li class="pkt-user-menu__item">
                  <div class="pkt-user-menu__label">Representerer</div>
                  <div class="pkt-user-menu__name" translate="no">${this.representing.name}</div>
                  ${this.representing.orgNumber
                    ? html`<div class="pkt-user-menu__org-number">
                        Org.nr. ${this.representing.orgNumber}
                      </div>`
                    : nothing}
                  ${this.canChangeRepresentation
                    ? html`
                        <ul class="pkt-user-menu__sublist mt-size-16">
                          <li class="pkt-user-menu__subitem">
                            ${this.renderLinkOrButton({
                              title: 'Endre organisasjon',
                              iconName: 'cogwheel',
                              onClick: () => this.handleChangeRepresentation(),
                            })}
                          </li>
                        </ul>
                      `
                    : nothing}
                </li>
              `
            : nothing}

          <!-- Change representation without representing object -->
          ${!this.representing && this.canChangeRepresentation
            ? html`
                <li class="pkt-user-menu__item">
                  <ul class="pkt-user-menu__sublist">
                    <li class="pkt-user-menu__subitem">
                      ${this.renderLinkOrButton({
                        title: 'Endre organisasjon',
                        iconName: 'cogwheel',
                        onClick: () => this.handleChangeRepresentation(),
                      })}
                    </li>
                  </ul>
                </li>
              `
            : nothing}

          <!-- Logout -->
          ${this.logoutOnClick
            ? html`
                <li class="pkt-user-menu__item">
                  ${this.renderLinkOrButton({
                    title: 'Logg ut',
                    iconName: 'exit',
                    onClick: () => this.handleLogout(),
                  })}
                </li>
              `
            : nothing}
        </ul>
      </nav>
    `
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'pkt-header-user-menu': PktHeaderUserMenu
  }
}

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