import { html, nothing, TemplateResult } from 'lit'
import { query } from 'lit/decorators.js'
import { live } from 'lit/directives/live.js'
import type { IApiKeyAuthorization } from '@api-client/core/models/Authorization.js'
import { Authorization } from './Authorization.js'
import Input from '../../../md/input/Input.js'
import '../../../md/text-field/ui-filled-text-field.js'
import '../../../md/list/ui-list.js'
import '../../../md/list/ui-list-item.js'
import '../../../md/dropdown-list/ui-dropdown-list.js'
import '../../../md/icons/ui-icon.js'

const LabelsMap: Record<keyof IApiKeyAuthorization, string> = {
  cookie: 'Cookies',
  header: 'Headers',
  query: 'Query string',
  path: 'URL path',
}

export default class ApiKeyAuthorization extends Authorization {
  @query('[name="key"]') accessor keyInput!: Input

  @query('[name="value"]') accessor valueInput!: Input

  get keyLocation(): keyof IApiKeyAuthorization {
    const { authorization } = this
    if (!authorization) {
      return 'query'
    }
    const config = (authorization.config as IApiKeyAuthorization) || ({} as IApiKeyAuthorization)
    if (config.cookie) {
      return 'cookie'
    }
    if (config.header) {
      return 'header'
    }
    return 'query'
  }

  override checkValidity(): boolean {
    const { elements } = this.form
    return !Array.from(elements).some((node) => !(node as Input).checkValidity())
  }

  protected handleChange(): void {
    const { authorization } = this
    if (!authorization) {
      return
    }
    if (!authorization.config) {
      authorization.config = {} as IApiKeyAuthorization
    }
    const { value: keyName } = this.keyInput
    const { value } = this.valueInput
    if (!keyName) {
      return
    }
    authorization.config = {
      [this.keyLocation]: {
        [keyName]: value,
      },
    } as IApiKeyAuthorization
    this.notifyChange()
  }

  protected handleLocationChange(e: CustomEvent): void {
    const target = e.detail.item as HTMLElement | undefined
    if (!target) {
      return
    }
    const { authorization } = this
    if (!authorization) {
      return
    }
    const config = (authorization.config as IApiKeyAuthorization) || ({} as IApiKeyAuthorization)
    const selected = target.dataset.value as keyof IApiKeyAuthorization
    const currentKey = this.keyLocation
    const currentValue = config[currentKey]
    authorization.config = {
      [selected]: currentValue || {},
    }
    this.notifyChange()
    this.requestUpdate()
  }

  override render(): TemplateResult {
    return html` ${this.renderHeader()} ${this.renderEditor()} `
  }

  protected renderEditor(): TemplateResult | typeof nothing {
    const { authorization } = this
    if (!authorization) {
      return nothing
    }
    const config = (authorization.config as IApiKeyAuthorization) || ({} as IApiKeyAuthorization)
    return html`
      <form autocomplete="on" class="auth-form basic-auth">
        ${this.renderKeyName(config)} ${this.renderKeyValue(config)} ${this.renderLocation()}
      </form>
      ${this.renderAuthInfo()}
    `
  }

  protected renderKeyName(config: IApiKeyAuthorization): TemplateResult {
    const { keyLocation } = this
    let value: string | undefined
    const map = config[keyLocation]
    if (map) {
      ;[value] = Object.keys(map)
    }
    return html`
      <div class="full-input">
        <ui-filled-text-field
          label="Key name"
          name="key"
          .value="${live(value || '')}"
          required
          invalidText="The key name is required"
          ?disabled="${this.disabled}"
          ?readOnly="${this.readOnly}"
          @change="${this.handleChange}"
        ></ui-filled-text-field>
      </div>
    `
  }

  protected renderKeyValue(config: IApiKeyAuthorization): TemplateResult {
    const { keyLocation } = this
    let value: string | undefined
    const map = config[keyLocation]
    if (map) {
      const key = Object.keys(map)[0]
      if (key) {
        value = map[key]
      }
    }
    return html`
      <div class="full-input">
        <ui-filled-text-field
          label="Value"
          name="value"
          type="password"
          .value="${live(value || '')}"
          required
          invalidText="The key is required"
          ?disabled="${this.disabled}"
          ?readOnly="${this.readOnly}"
          @change="${this.handleChange}"
        ></ui-filled-text-field>
      </div>
    `
  }

  protected renderLocation(): TemplateResult {
    const { keyLocation } = this
    const label = LabelsMap[keyLocation]
    return html`
      <ui-dropdown-list
        verticalAlign="top"
        @select="${this.handleLocationChange}"
        class="type-dropdown"
        closeOnOutsideClick
      >
        <ui-filled-text-field readOnly name="location" .value="${label}" label="Key location">
          <ui-icon slot="suffix" icon="arrowDropDown" role="presentation"></ui-icon>
        </ui-filled-text-field>
        <ui-list slot="dropdown" role="menu">
          <ui-list-item role="menuitem" data-value="query" title="Place the key in the query string"
            >${LabelsMap.query}</ui-list-item
          >
          <ui-list-item role="menuitem" data-value="header" title="Place the key in the header value"
            >${LabelsMap.header}</ui-list-item
          >
          <ui-list-item role="menuitem" data-value="cookie" title="Place the key in the cookies value"
            >${LabelsMap.cookie}</ui-list-item
          >
        </ui-list>
      </ui-dropdown-list>
    `
  }
}
