import type { DomainProperty } from '@api-client/core/modeling/DomainProperty.js'
import { type HTMLConfig, DEFAULT_HTML_CONFIG } from '@api-client/core/modeling/definitions/HTML.js'
import { bound } from '../../decorators/bound.js'
import { html, TemplateResult } from 'lit'
import { SemanticType } from '@api-client/core/modeling/Semantics.js'
import { renderHelp } from '../../help/render.js'
import { TaxonomyDialog } from './TaxonomyDialog.js'

import '../../md/chip/ui-chip-set.js'
import '../../md/chip/ui-chip.js'

/**
 * A class that generates a dialog that allows the user to configure the taxonomy of a HTML field.
 */
export class HtmlTaxonomy extends TaxonomyDialog<HTMLConfig> {
  static override title = `Configure HTML Taxonomy`

  constructor(public domainElement: DomainProperty) {
    let config: HTMLConfig
    const semantic = domainElement.semantics.find((s) => s.id === SemanticType.HTML)
    if (semantic && semantic.config) {
      config = structuredClone(semantic.config)
    } else {
      config = {}
    }
    super(config)
  }

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

  @bound
  protected handleAllowedTagsChange(event: Event): void {
    const input = event.target as HTMLInputElement
    const value = input.value.trim()
    if (value) {
      const tags = this.config?.allowedTags ?? DEFAULT_HTML_CONFIG.allowedTags ?? []
      if (!tags.includes(value)) {
        tags.push(value)
        this.config = { ...this.config, allowedTags: tags }
        this.requestUpdate()
      }
      input.value = ''
    }
  }

  @bound
  protected handleRemoveTag(event: Event): void {
    const chip = event.currentTarget as HTMLElement
    const index = parseInt(chip.dataset.index || '-1', 10)
    if (index >= 0 && this.config?.allowedTags) {
      this.config.allowedTags.splice(index, 1)
      this.requestUpdate()
    }
  }

  @bound
  render(): TemplateResult {
    return html`
      <div class="checkbox-group">
        ${this.renderAllowImages()} ${this.renderAllowLinks()} ${this.renderAllowTables()} ${this.renderAllowForms()}
        ${this.renderAllowScripts()} ${this.renderAllowIframes()} ${this.renderAllowEmbedded()}
        ${this.renderAllowStyles()} ${this.renderAllowDataAttributes()}
      </div>
      <div class="input-group">
        ${this.renderRenderModeSelect()} ${this.renderSanitizeLevelSelect()} ${this.renderAllowedTagsInput()}
      </div>
    `
  }

  protected renderAllowImages(): TemplateResult {
    const enabled = this.config?.allowImages ?? DEFAULT_HTML_CONFIG.allowImages
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-images"
            .checked="${enabled}"
            name="allowImages"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-images" class="body-medium">Allow Images</label>
            <span class="body-small meta">Users are allowed to add images in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowImages')}
      </div>
    `
  }

  protected renderAllowLinks(): TemplateResult {
    const enabled = this.config?.allowLinks ?? DEFAULT_HTML_CONFIG.allowLinks
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-links"
            .checked="${enabled}"
            name="allowLinks"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-links" class="body-medium">Allow Links</label>
            <span class="body-small meta">Users are allowed to add links in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowLinks')}
      </div>
    `
  }

  protected renderAllowTables(): TemplateResult {
    const enabled = this.config?.allowTables ?? DEFAULT_HTML_CONFIG.allowTables
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-tables"
            .checked="${enabled}"
            name="allowTables"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-tables" class="body-medium">Allow Tables</label>
            <span class="body-small meta">Users are allowed to add tables in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowTables')}
      </div>
    `
  }

  protected renderAllowForms(): TemplateResult {
    const enabled = this.config?.allowForms ?? DEFAULT_HTML_CONFIG.allowForms
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-forms"
            .checked="${enabled}"
            name="allowForms"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-forms" class="body-medium">Allow Forms</label>
            <span class="body-small meta">Users are allowed to add forms in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowForms')}
      </div>
    `
  }

  protected renderAllowScripts(): TemplateResult {
    const enabled = this.config?.allowScripts ?? DEFAULT_HTML_CONFIG.allowScripts
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-scripts"
            .checked="${enabled}"
            name="allowScripts"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-scripts" class="body-medium">Allow Scripts</label>
            <span class="body-small meta">Users are allowed to add scripts in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowScripts')}
      </div>
    `
  }

  protected renderAllowIframes(): TemplateResult {
    const enabled = this.config?.allowIframes ?? DEFAULT_HTML_CONFIG.allowIframes
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-iframes"
            .checked="${enabled}"
            name="allowIframes"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-iframes" class="body-medium">Allow Iframes</label>
            <span class="body-small meta">Users are allowed to add iframes in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowIframes')}
      </div>
    `
  }

  protected renderAllowEmbedded(): TemplateResult {
    const enabled = this.config?.allowEmbedded ?? DEFAULT_HTML_CONFIG.allowEmbedded
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-embedded"
            .checked="${enabled}"
            name="allowEmbedded"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-embedded" class="body-medium">Allow Embedded Content</label>
            <span class="body-small meta">Users are allowed to add embedded content in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowEmbedded')}
      </div>
    `
  }

  protected renderAllowStyles(): TemplateResult {
    const enabled = this.config?.allowStyles ?? DEFAULT_HTML_CONFIG.allowStyles
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-styles"
            .checked="${enabled}"
            name="allowStyles"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-styles" class="body-medium">Allow Styles</label>
            <span class="body-small meta">Users are allowed to add styles in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowStyles')}
      </div>
    `
  }

  protected renderAllowDataAttributes(): TemplateResult {
    const enabled = this.config?.allowDataAttributes ?? DEFAULT_HTML_CONFIG.allowDataAttributes
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-data-attributes"
            .checked="${enabled}"
            name="allowDataAttributes"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-data-attributes" class="body-medium">Allow Data Attributes</label>
            <span class="body-small meta">Users are allowed to add data attributes in their HTML content.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'html:allowDataAttributes')}
      </div>
    `
  }

  protected renderRenderModeSelect(): TemplateResult {
    const value = this.config?.renderMode ?? DEFAULT_HTML_CONFIG.renderMode
    return html`
      <div class="row input-row">
        <ui-select
          label="Render mode"
          class="input"
          name="renderMode"
          .value="${value as string}"
          @change="${this.handleSelectChange}"
        >
          <ui-option value="html">HTML</ui-option>
          <ui-option value="text">Text</ui-option>
          <ui-option value="both">Both</ui-option>
        </ui-select>
        ${renderHelp('taxonomy', 'html:renderMode')}
      </div>
    `
  }

  protected renderSanitizeLevelSelect(): TemplateResult {
    const value = this.config?.sanitizeLevel ?? DEFAULT_HTML_CONFIG.sanitizeLevel
    return html`
      <div class="row input-row">
        <ui-select
          label="Sanitize level"
          class="input"
          name="sanitizeLevel"
          .value="${value as string}"
          @change="${this.handleSelectChange}"
        >
          <ui-option value="strict">Strict</ui-option>
          <ui-option value="moderate">Moderate</ui-option>
          <ui-option value="none">None</ui-option>
        </ui-select>
        ${renderHelp('taxonomy', 'html:sanitizeLevel')}
      </div>
    `
  }

  protected renderAllowedTagsInput(): TemplateResult {
    const value = this.config?.allowedTags ?? DEFAULT_HTML_CONFIG.allowedTags
    const chips = (value || []).map(
      (tag, index) =>
        html`<ui-chip type="input" removable data-index="${index}" @remove="${this.handleRemoveTag}">${tag}</ui-chip>`
    )
    return html`
      <div class="row input-row">
        <div class="input chips-input">
          <ui-outlined-text-field
            class="input"
            name="allowedTags"
            label="Allowed Tags"
            @change="${this.handleAllowedTagsChange}"
            supportingText="Add a tag and press Enter to add it to the list."
          ></ui-outlined-text-field>
          <ui-chip-set>${chips}</ui-chip-set>
        </div>
        ${renderHelp('taxonomy', 'html:allowedTags')}
      </div>
    `
  }
}
