import type { DomainProperty } from '@api-client/core/modeling/DomainProperty.js'
import { bound } from '../../decorators/bound.js'
import { html, nothing, TemplateResult } from 'lit'
import { DEFAULT_PASSWORD_CONFIG, type PasswordConfig } from '@api-client/core/modeling/definitions/Password.js'
import { SemanticType } from '@api-client/core/modeling/Semantics.js'
import { live } from 'lit/directives/live.js'
import { renderHelp } from '../../help/render.js'
import { ifDefined } from 'lit/directives/if-defined.js'
import { TaxonomyDialog } from './TaxonomyDialog.js'

/**
 * A class that generates a dialog that allows the user to configure the taxonomy of a password.
 */
export class PasswordTaxonomy extends TaxonomyDialog<PasswordConfig> {
  static override title = `Configure Password Taxonomy`

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

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

  @bound
  render(): TemplateResult {
    return html`
      <div class="checkbox-group">
        ${this.renderRequireSpecialChars()} ${this.renderRequireNumbers()} ${this.renderRequireUppercase()}
        ${this.renderRequireLowercase()} ${this.renderPreventReuse()}
      </div>
      <div class="input-group">${this.renderReuseCountInput()} ${this.renderMaxAgeInput()}</div>
    `
  }

  protected renderRequireSpecialChars(): TemplateResult {
    const enabled = this.config?.requireSpecialChars ?? false
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="require-special-chars"
            .checked="${enabled}"
            name="requireSpecialChars"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="require-special-chars" class="body-medium">Require Special Characters</label>
            <span class="body-small meta">Users must add special characters in their passwords.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'password:requireSpecialChars')}
      </div>
    `
  }

  protected renderRequireNumbers(): TemplateResult {
    const enabled = this.config?.requireNumbers ?? DEFAULT_PASSWORD_CONFIG.requireNumbers
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="require-numbers"
            .checked="${enabled}"
            name="requireNumbers"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="require-numbers" class="body-medium">Require Numbers</label>
            <span class="body-small meta">Users must add numbers to their passwords.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'password:requireNumbers')}
      </div>
    `
  }

  protected renderRequireUppercase(): TemplateResult {
    const enabled = this.config?.requireUppercase ?? DEFAULT_PASSWORD_CONFIG.requireUppercase
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="require-uppercase"
            .checked="${enabled}"
            name="requireUppercase"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="require-uppercase" class="body-medium">Require Uppercase Letters</label>
            <span class="body-small meta">Users must add uppercase letters to their passwords.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'password:requireUppercase')}
      </div>
    `
  }

  protected renderRequireLowercase(): TemplateResult {
    const enabled = this.config?.requireLowercase ?? DEFAULT_PASSWORD_CONFIG.requireLowercase
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="require-lowercase"
            .checked="${enabled}"
            name="requireLowercase"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="require-lowercase" class="body-medium">Require Lowercase Letters</label>
            <span class="body-small meta">Users must add lowercase letters to their passwords.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'password:requireLowercase')}
      </div>
    `
  }

  protected renderPreventReuse(): TemplateResult {
    const enabled = this.config?.preventReuse ?? DEFAULT_PASSWORD_CONFIG.preventReuse
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="prevent-reuse"
            .checked="${enabled}"
            name="preventReuse"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="prevent-reuse" class="body-medium">Prevent Reuse</label>
            <span class="body-small meta">Prevents users from reusing old passwords.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'password:preventReuse')}
      </div>
    `
  }

  protected renderReuseCountInput(): TemplateResult | typeof nothing {
    const enabled = this.config?.preventReuse ?? DEFAULT_PASSWORD_CONFIG.preventReuse
    if (!enabled) {
      return nothing
    }
    const value = this.config?.preventReuseCount ?? DEFAULT_PASSWORD_CONFIG.preventReuseCount
    return html`
      <div class="row input-row">
        <ui-outlined-text-field
          class="input"
          name="preventReuseCount"
          .value="${live(String(value))}"
          label="Reuse count history"
          required
          min="1"
          type="number"
          @change="${this.handleTextChange}"
          supportingText="Number of previous passwords to remember."
        ></ui-outlined-text-field>
        ${renderHelp('taxonomy', 'password:preventReuseCount')}
      </div>
    `
  }

  protected renderMaxAgeInput(): TemplateResult {
    const info = 'Maximum age of password in days before requiring change.'
    const value = this.config?.maxAge ?? DEFAULT_PASSWORD_CONFIG.maxAge
    return html`
      <div class="row input-row">
        <ui-outlined-text-field
          class="input"
          name="maxAge"
          value="${ifDefined(value as unknown as string)}"
          label="Max age (in days)"
          min="0"
          type="number"
          @change="${this.handleTextChange}"
          .supportingText="${info}"
        ></ui-outlined-text-field>
        ${renderHelp('taxonomy', 'password:maxAge')}
      </div>
    `
  }
}
