import type { DomainProperty } from '@api-client/core/modeling/DomainProperty.js'
import { bound } from '../../decorators/bound.js'
import { type CurrencyConfig, DEFAULT_CURRENCY_CONFIG } from '@api-client/core/modeling/definitions/Currency.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'
import '../../elements/currency/currency-picker.js'

/**
 * A class that generates a dialog that allows the user to configure the taxonomy of a price/currency field.
 */
export class CurrencyTaxonomy extends TaxonomyDialog<CurrencyConfig> {
  static override title = `Configure Currency Taxonomy`

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

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

  protected handleAllowedCurrenciesChange(event: Event): void {
    const currencyPicker = event.target as HTMLElement & { selected: string[] }
    const selectedCodes = currencyPicker.selected || []
    this.config = { ...this.config, allowedCurrencies: selectedCodes.length > 0 ? selectedCodes : undefined }
    this.requestUpdate()
  }

  protected handleDecimalPlacesChange(event: Event): void {
    const input = event.target as HTMLInputElement
    const value = parseInt(input.value, 10)
    if (!isNaN(value) && value >= 0 && value <= 8) {
      this.config = { ...this.config, decimalPlaces: value }
      this.requestUpdate()
    }
  }

  protected handleDefaultCurrencyChange(event: Event): void {
    const currencyPicker = event.target as HTMLElement & { selected: string[] }
    const selectedCodes = currencyPicker.selected || []
    if (selectedCodes.length > 0) {
      const selectedCurrency = selectedCodes[0]
      this.config = { ...this.config, defaultCurrency: selectedCurrency }
    } else {
      this.config = { ...this.config, defaultCurrency: undefined }
    }
  }

  @bound
  render(): TemplateResult {
    return html`
      <div class="input-group">
        ${this.renderStorageFormatSelect()} ${this.renderDecimalPlacesInput()} ${this.renderAllowedCurrenciesInput()}
        ${this.renderDefaultCurrencyInput()}
      </div>
      <div class="checkbox-group">${this.renderAllowNegative()} ${this.renderValidateCurrencyCode()}</div>
    `
  }

  protected renderStorageFormatSelect(): TemplateResult {
    const value = this.config?.storageFormat ?? DEFAULT_CURRENCY_CONFIG.storageFormat
    return html`
      <div class="row">
        <ui-select
          label="Storage Format"
          class="input"
          name="storageFormat"
          .value="${value as string}"
          @change="${this.handleSelectChange}"
        >
          <ui-option value="decimal">
            <div>Decimal</div>
            <div slot="supporting-text">Store as DECIMAL/NUMERIC (e.g., 19.99)</div>
          </ui-option>
          <ui-option value="integer_cents">
            <div>Integer Cents</div>
            <div slot="supporting-text">Store as INTEGER in smallest unit (e.g., 1999 for $19.99)</div>
          </ui-option>
          <ui-option value="complex_object">
            <div>Complex Object</div>
            <div slot="supporting-text">Store as JSON with amount and currency</div>
          </ui-option>
        </ui-select>
        ${renderHelp('taxonomy', 'currency:storageFormat')}
      </div>
    `
  }

  protected renderDecimalPlacesInput(): TemplateResult {
    const valueRaw = this.config?.decimalPlaces ?? DEFAULT_CURRENCY_CONFIG.decimalPlaces
    const value = valueRaw !== undefined ? valueRaw.toString() : ''
    return html`
      <div class="row input-row">
        <ui-outlined-text-field
          class="input"
          name="decimalPlaces"
          type="number"
          .value="${value}"
          label="Decimal Places"
          min="0"
          max="8"
          step="1"
          supportingText="Number of decimal places for precision (0-8)"
          @change="${this.handleDecimalPlacesChange}"
        ></ui-outlined-text-field>
        ${renderHelp('taxonomy', 'currency:decimalPlaces')}
      </div>
    `
  }

  protected renderAllowedCurrenciesInput(): TemplateResult {
    const allowedCurrencies = this.config?.allowedCurrencies ?? DEFAULT_CURRENCY_CONFIG.allowedCurrencies ?? []
    return html`
      <div class="row input-row">
        <currency-picker
          label="Allowed Currencies"
          .selected="${allowedCurrencies}"
          @change="${this.handleAllowedCurrenciesChange}"
          multi
          class="input"
        ></currency-picker>
        ${renderHelp('taxonomy', 'currency:allowedCurrencies')}
      </div>
    `
  }

  protected renderDefaultCurrencyInput(): TemplateResult {
    const allowedCurrencies = this.config?.allowedCurrencies ?? DEFAULT_CURRENCY_CONFIG.allowedCurrencies ?? []
    const value = this.config?.defaultCurrency ?? DEFAULT_CURRENCY_CONFIG.defaultCurrency
    const selected = value && allowedCurrencies.includes(value) ? [value] : []
    return html`
      <div class="row  input-row">
        <currency-picker
          label="Default Currency"
          .selected="${selected}"
          .allowedCurrencies="${allowedCurrencies}"
          @change="${this.handleDefaultCurrencyChange}"
          name="defaultCurrency"
          class="input"
        ></currency-picker>
        ${renderHelp('taxonomy', 'currency:defaultCurrency')}
      </div>
    `
  }

  protected renderAllowNegative(): TemplateResult {
    const enabled = this.config?.allowNegative ?? DEFAULT_CURRENCY_CONFIG.allowNegative
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="allow-negative"
            .checked="${enabled}"
            name="allowNegative"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="allow-negative" class="body-medium">Allow Negative Values</label>
            <span class="body-small meta">Allow negative amounts for refunds, discounts, etc.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'currency:allowNegative')}
      </div>
    `
  }

  protected renderValidateCurrencyCode(): TemplateResult {
    const enabled = this.config?.validateCurrencyCode ?? DEFAULT_CURRENCY_CONFIG.validateCurrencyCode
    return html`
      <div class="row">
        <div class="input checkbox metadata">
          <ui-checkbox
            id="validate-currency-code"
            .checked="${enabled}"
            name="validateCurrencyCode"
            @change="${this.handleBooleanChange}"
          ></ui-checkbox>
          <div class="label">
            <label for="validate-currency-code" class="body-medium">Validate Currency Codes</label>
            <span class="body-small meta">Automatically validate currency codes against ISO 4217 standard.</span>
          </div>
        </div>
        ${renderHelp('taxonomy', 'currency:validateCurrencyCode')}
      </div>
    `
  }
}
