/**
 * Non-side-effect class export for `<textarea-ui>`.
 *
 * Importing this file gives you the class(es) without auto-registering the tag.
 * Useful for test isolation, subclassing with tag-name override, or selective
 * composition.
 *
 * The auto-register path stays at `@adia-ai/web-components/components/textarea`
 * (which imports this file + calls `defineIfFree()`).
 *
 * @see ../../USAGE.md#registration--auto-vs-explicit
 */

/**
 * <textarea-ui> — Multiline text input. The host IS the interactive surface.
 * Uses contenteditable for text entry, ElementInternals for form participation.
 * No native <textarea> inside.
 */

import { UIFormElement } from '../../core/form.js';

export class UITextarea extends UIFormElement {
  static labelDeprecated = false;  // §170 (v0.5.4): label is first-class per textarea.yaml
  static properties = {
    ...UIFormElement.properties,
    placeholder: { type: String,  default: '', reflect: true },
    label:       { type: String,  default: '', reflect: true },
    rows:        { type: Number,  default: 3, reflect: true },
    resize:      { type: String,  default: 'vertical', reflect: true },
  };

  static template = () => null;

  #textEl = null;

  connected() {
    super.connected();
    this.setAttribute('role', 'textbox');
    this.setAttribute('aria-multiline', 'true');

    if (!this.querySelector('[slot="text"]')) {
      this.innerHTML = `
        ${this.label ? `<label slot="label" label="${this.label}"></label>` : ''}
        <div slot="text" contenteditable="plaintext-only" tabindex="0"
             ${this.value ? '' : 'data-empty=""'}
             data-placeholder="${this.placeholder}"></div>
      `;
    }

    this.#textEl = this.querySelector('[slot="text"]');
    if (this.value) this.#textEl.textContent = this.value;

    if (this.#textEl) {
      this.#textEl.addEventListener('input', this.#onInput);
      this.#textEl.addEventListener('keydown', this.#onKeydown);
      this.#textEl.addEventListener('blur', this.#onBlur);
      this.#textEl.addEventListener('paste', this.#onPaste);
    }
  }

  render() {
    if (!this.#textEl) return;

    this.#textEl.setAttribute('data-placeholder', this.placeholder);

    if (this.disabled || this.readonly) {
      this.#textEl.contentEditable = 'false';
    } else {
      this.#textEl.contentEditable = 'plaintext-only';
    }

    // Sync programmatic `value` assignments (form.reset(), trait writes,
    // controlled-input patterns) into the contenteditable surface. Skip
    // when the surface already matches to avoid clobbering an in-flight
    // edit's caret.
    const text = this.value || '';
    if (this.#textEl.textContent !== text) {
      this.#textEl.textContent = text;
      this.#textEl.toggleAttribute('data-empty', !text);
    }

    const label = this.querySelector('[slot="label"]');
    if (label && this.label) label.setAttribute('label', this.label);

    this.setAttribute('aria-label', this.label || this.placeholder || '');
  }

  #onInput = () => {
    const text = this.#textEl.textContent || '';
    this.value = text;
    this.#textEl.toggleAttribute('data-empty', !text);
    this.syncValue(text);
    // §220 (v0.5.9, FEEDBACK-14 §3): trailing-debounce when `throttle > 0`.
    this.scheduleThrottledInput();
  };

  #onKeydown = (e) => {
    // Enter without shift submits; shift+enter inserts newline
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      // §220: flush any pending throttled input before submit so listeners
      // observe the latest value.
      this.flushPendingInput();
      this.dispatchEvent(new Event('submit', { bubbles: true }));
    }
  };

  #onBlur = () => {
    // §220: trailing `input` precedes `change`.
    this.flushPendingInput();
    this.dispatchEvent(new CustomEvent('change', { bubbles: true, detail: { value: this.value } }));
  };

  #onPaste = (e) => {
    e.preventDefault();
    const text = e.clipboardData?.getData('text/plain') || '';
    document.execCommand('insertText', false, text);
  };

  focus() { this.#textEl?.focus(); }

  clear() {
    this.value = '';
    if (this.#textEl) {
      this.#textEl.textContent = '';
      this.#textEl.setAttribute('data-empty', '');
    }
    this.syncValue('');
  }

  disconnected() {
    super.disconnected();
    if (this.#textEl) {
      this.#textEl.removeEventListener('input', this.#onInput);
      this.#textEl.removeEventListener('keydown', this.#onKeydown);
      this.#textEl.removeEventListener('blur', this.#onBlur);
      this.#textEl.removeEventListener('paste', this.#onPaste);
    }
    this.#textEl = null;
  }
}
