import { TaxonomyDialog } from './TaxonomyDialog.js'
import type { DomainProperty } from '@api-client/core/modeling/DomainProperty.js'
import { SemanticType } from '@api-client/core/modeling/Semantics.js'
import { bound } from '../../decorators/bound.js'
import { html, nothing, TemplateResult } from 'lit'
import { renderHelp } from '../../help/render.js'
import {
  type PublicUniqueNameConfig,
  DEFAULT_PUBLIC_UNIQUE_NAME_CONFIG,
} from '@api-client/core/modeling/definitions/PublicUniqueName.js'
import { repeat } from 'lit/directives/repeat.js'

export class PublicUniqueNameTaxonomy extends TaxonomyDialog<PublicUniqueNameConfig> {
  static override title = `Configure Public Unique Name Taxonomy`

  /**
   * The list of properties available for source list.
   * It is a computed list for the parent entity and all its parents.
   */
  properties: DomainProperty[] = []

  /**
   * The default source field to use for the public unique name.
   * It is the first property with the `Title` semantic.
   */
  defaultSourceField?: DomainProperty

  constructor(public domainElement: DomainProperty) {
    let config: PublicUniqueNameConfig
    const semantic = domainElement.semantics.find((s) => s.id === SemanticType.PublicUniqueName)
    if (semantic && semantic.config) {
      config = structuredClone(semantic.config) as PublicUniqueNameConfig
    } else {
      config = {}
    }
    super(config)
    const entity = domainElement.getParentInstance()
    if (entity) {
      this.properties = this.listComputedProperties(entity, {
        exclude: [this.domainElement.key],
        types: ['string'],
      })
      this.defaultSourceField = this.properties.find((prop) => prop.hasSemantic(SemanticType.Title))
    }
  }

  protected override formCallback(event: Event): Promise<void> {
    const semantic = this.domainElement.semantics.find((s) => s.id === SemanticType.PublicUniqueName)
    if (semantic) {
      semantic.config = this.config
    } else {
      this.domainElement.semantics.push({
        id: SemanticType.PublicUniqueName,
        config: this.config,
      })
    }
    this.domainElement.domain.notifyChange()
    return super.formCallback(event)
  }

  @bound
  render(): TemplateResult {
    return html`
      <div class="input-group">
        ${this.renderSourceFieldInput()} ${this.renderFallbackFieldInput()} ${this.renderSeparatorInput()}
      </div>
      <div class="checkbox-group">
        ${this.renderCaseSensitive()} ${this.renderAllowUnicode()} ${this.renderAllowDuplicates()}
      </div>
    `
  }

  protected renderSourceFieldInput(): TemplateResult {
    const value = this.config?.sourceField ?? this.defaultSourceField?.key
    return html`
      <div class="row input-row">
        <ui-select
          label="Source Field"
          class="input"
          name="sourceField"
          required
          .value="${value as string}"
          @change="${this.handleSelectChange}"
        >
          ${repeat(
            this.properties,
            (prop) => prop.key,
            (prop) => {
              return html`
                <ui-option value="${prop.key}">
                  <div>${prop.info.getLabel()}</div>
                  ${prop.info.description ? html`<div slot="supporting-text">${prop.info.description}</div>` : nothing}
                </ui-option>
              `
            }
          )}
        </ui-select>
        ${renderHelp('taxonomy', 'publicuniquename:sourceField')}
      </div>
    `
  }

  protected renderFallbackFieldInput(): TemplateResult {
    const value = this.config?.fallbackField
    return html`
      <div class="row input-row">
        <ui-select
          label="Fallback Field"
          class="input"
          name="fallbackField"
          .value="${value as string}"
          @change="${this.handleSelectChange}"
          supportingText="If the source field is empty, this field will be used as a fallback."
        >
          ${repeat(
            this.properties,
            (prop) => prop.key,
            (prop) => {
              return html`
                <ui-option value="${prop.key}">
                  <div>${prop.info.getLabel()}</div>
                  ${prop.info.description ? html`<div slot="supporting-text">${prop.info.description}</div>` : nothing}
                </ui-option>
              `
            }
          )}
        </ui-select>
        ${renderHelp('taxonomy', 'publicuniquename:fallbackField')}
      </div>
    `
  }

  protected renderSeparatorInput(): TemplateResult {
    const value = this.config?.separator ?? DEFAULT_PUBLIC_UNIQUE_NAME_CONFIG.separator
    return html`
      <div class="row input-row">
        <ui-outlined-text-field
          label="Separator"
          class="input"
          name="separator"
          .value="${value as string}"
          @change="${this.handleTextChange}"
          required
        ></ui-outlined-text-field>
        ${renderHelp('taxonomy', 'publicuniquename:separator')}
      </div>
    `
  }

  protected renderCaseSensitive(): TemplateResult {
    const enabled = this.config?.caseSensitive ?? DEFAULT_PUBLIC_UNIQUE_NAME_CONFIG.caseSensitive
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="case-sensitive"
            .checked="${enabled}"
            name="caseSensitive"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="case-sensitive" class="body-medium">Case Sensitive</label>
            <span class="body-small meta">Whether the public unique name is case sensitive.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'publicuniquename:caseSensitive')}
      </div>
    `
  }

  protected renderAllowUnicode(): TemplateResult {
    const enabled = this.config?.allowUnicode ?? DEFAULT_PUBLIC_UNIQUE_NAME_CONFIG.allowUnicode
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-unicode"
            .checked="${enabled}"
            name="allowUnicode"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-unicode" class="body-medium">Allow Unicode Characters</label>
            <span class="body-small meta">Whether to allow Unicode characters in the public unique name.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'publicuniquename:allowUnicode')}
      </div>
    `
  }

  protected renderAllowDuplicates(): TemplateResult {
    const enabled = this.config?.allowDuplicates ?? DEFAULT_PUBLIC_UNIQUE_NAME_CONFIG.allowDuplicates
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-duplicates"
            .checked="${enabled}"
            name="allowDuplicates"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-duplicates" class="body-medium">Allow Duplicates</label>
            <span class="body-small meta">Whether to allow duplicate public unique names.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'publicuniquename:allowDuplicates')}
      </div>
    `
  }
}
