import { html, nothing, TemplateResult } from 'lit'
import { property } from 'lit/decorators.js'
import { DataTable } from '../DataTable.js'
import { UserKind } from '@api-client/core/models/kinds.js'
import type { UiMenuElement } from '../../../md/menu/ui-menu.js'
import type { OrgUser } from '../../../data/UsersModel.js'
import type { LiveData } from '../../../reactive/LiveData.js'
import type { IUser } from '@api-client/core/models/store/User.js'
import type { InvitationSchema } from '@api-client/core/models/store/Invitation.js'
import type { UiMenuItemElement } from '../../../md/menu/ui-menu-item.js'

import '../../../md/icon-button/ui-icon-button.js'
import '../../../md/icons/ui-icon.js'
import '../../../md/divider/ui-divider.js'
import '../../../md/menu/ui-menu.js'
import '../../../md/menu/ui-menu-item.js'

/**
 * @fires rowaction - When a menu item is clicked, this event is fired with the user key, kind, and action.
 */
export default class UsersDataTable extends DataTable<OrgUser> {
  /**
   * The current user id.
   */
  @property({ type: String }) accessor current: string | undefined

  override get items(): LiveData<OrgUser[]> | undefined {
    return super.items
  }

  override set items(value: LiveData<OrgUser[]> | undefined) {
    super.items = value
  }

  constructor() {
    super()
    this.addEventListener('click', this.handleTableClick.bind(this))
  }

  handleTableClick(e: Event): void {
    const target = e.composedPath()[0] as HTMLElement
    if (target.nodeType !== Node.ELEMENT_NODE) {
      return
    }
    if (target.classList.contains('user-link')) {
      e.preventDefault()
      const { key, kind } = target.dataset
      if (!key || !kind) {
        return
      }
      this.dispatchEvent(new CustomEvent('rowaction', { detail: { key, kind, action: 'open' } }))
    }
  }

  handleMenuSelect(e: CustomEvent<{ item: UiMenuItemElement }>): void {
    const menu = e.currentTarget as UiMenuElement
    const { key, kind } = menu.dataset
    if (!key || !kind) {
      return
    }
    const action = e.detail.item.value
    if (!action) {
      return
    }
    this.dispatchEvent(new CustomEvent('rowaction', { detail: { key, kind, action } }))
  }

  override renderHeader(): TemplateResult[] {
    return [
      this.renderHeaderCell('Name', 0, { sort: 'name' }),
      this.renderHeaderCell('Email', 1),
      this.renderHeaderCell('Role', 2),
      this.renderHeaderCell('Status', 3),
      this.renderHeaderCell(html`<span hidden aria-label="Row options">Menu</span>`, 4, { delegateFocus: true }),
    ]
  }

  override renderRowValues(item: OrgUser, index: number): TemplateResult[] {
    return [
      this.#nameCell(item, index, 0),
      this.#emailCell(item, index, 1),
      this.#roleCell(item, index, 2),
      this.#statusCell(item, index, 3),
      this.renderCell(this.#renderRowMenu(item), index, 4, { classes: ['actions'], delegateFocus: true }),
    ]
  }

  #nameCell(item: OrgUser, row: number, col: number): TemplateResult {
    let name = item.name || '(none)'
    if (this.current === item.key) {
      name += ' (You)'
    }
    let content: TemplateResult | string
    let delegateFocus = false
    if (item.kind === UserKind) {
      content = html`<a href="#/${item.key}" data-key="${item.key}" data-kind="${item.kind}" class="user-link"
        >${name}</a
      >`
      delegateFocus = true
    } else {
      content = name
    }
    return this.renderCell(content, row, col, { classes: ['primary-cell'], isPrimary: true, delegateFocus })
  }

  #emailCell(item: OrgUser, row: number, col: number): TemplateResult {
    let email: string | undefined
    if (item.kind === UserKind) {
      if (Array.isArray(item.email) && item.email.length > 0) {
        email = item.email[0]?.email
      }
    } else {
      email = item.email
    }
    let content: TemplateResult | string
    if (email) {
      content = html`<a href="mailto:${email}" class="email-link">${email}</a>`
    } else {
      content = '--'
    }
    return this.renderCell(content, row, col, { classes: ['email'] })
  }

  #roleCell(item: OrgUser, row: number, col: number): TemplateResult {
    let role = '--'
    if (item.grantType === 'owner') {
      role = 'Owner'
    } else if (item.grantType === 'manager') {
      role = 'Manager'
    } else if (item.grantType === 'editor') {
      role = 'Editor'
    } else if (item.grantType === 'viewer') {
      role = 'Viewer'
    }
    return this.renderCell(role, row, col, { classes: ['role'] })
  }

  #statusCell(item: OrgUser, row: number, col: number): TemplateResult {
    let status = 'Active'
    if (item.status === 'deleted') {
      status = 'Deleted'
    } else if (item.status === 'pending') {
      status = 'Invitation sent'
    } else if (item.status === 'suspended') {
      status = 'Suspended'
    } else if (item.status === 'declined') {
      status = 'Declined'
    }
    return this.renderCell(status, row, col, { classes: ['status'] })
  }

  #renderRowMenu(item: OrgUser): TemplateResult {
    return item.kind === UserKind ? this.#renderUserOptions(item) : this.#renderInviteOptions(item)
  }

  #renderUserOptions(item: IUser): TemplateResult {
    const { key, kind, status } = item
    const self = this.current === key
    return html`
      <ui-icon-button
        data-key="${key}"
        data-kind="${kind}"
        id="anchor-${key}"
        aria-controls="menu-${key}"
        tabindex="-1"
        popoverTarget="menu-${key}"
      >
        <ui-icon>more_vert</ui-icon>
      </ui-icon-button>
      <ui-menu
        class="item-menu"
        popover="auto"
        id="menu-${key}"
        data-key="${key}"
        data-kind="${kind}"
        @select="${this.handleMenuSelect}"
      >
        <ui-menu-item value="open">
          <div>Details</div>
          <ui-icon slot="start">info</ui-icon>
        </ui-menu-item>
        ${status === 'active'
          ? html`<ui-menu-item value="deactivate" ?disabled="${self}">
              <div>Deactivate</div>
              <ui-icon slot="start">person_off</ui-icon>
            </ui-menu-item>`
          : nothing}
        ${status === 'suspended'
          ? html`<ui-menu-item value="activate" ?disabled="${self}">
              <div>Reactivate</div>
              <ui-icon slot="start">person_check</ui-icon>
            </ui-menu-item>`
          : nothing}

        <ui-divider role="separator"></ui-divider>
        <ui-menu-item value="delete" ?disabled="${self}">
          <div>Delete</div>
          <ui-icon slot="start">delete</ui-icon>
        </ui-menu-item>
      </ui-menu>
    `
  }

  #renderInviteOptions(item: InvitationSchema): TemplateResult {
    const { key, kind } = item
    return html`
      <ui-icon-button
        data-key="${key}"
        data-kind="${kind}"
        id="anchor-${key}"
        aria-controls="menu-${key}"
        tabindex="-1"
        popoverTarget="menu-${key}"
        aria-label="More options for the invitation to ${item.name || item.email}"
      >
        <ui-icon>more_vert</ui-icon>
      </ui-icon-button>
      <ui-menu
        class="item-menu"
        popover="auto"
        id="menu-${key}"
        data-key="${key}"
        data-kind="${kind}"
        @select="${this.handleMenuSelect}"
      >
        <ui-menu-item value="resend">
          <div>Resend</div>
          <ui-icon slot="start">send</ui-icon>
        </ui-menu-item>
        <ui-divider role="separator"></ui-divider>
        <ui-menu-item value="delete">
          <div>Cancel invitation</div>
          <ui-icon slot="start">delete</ui-icon>
        </ui-menu-item>
      </ui-menu>
    `
  }
}
