import { UIElement } from '../../core/element.js';
import '../../../web-modules/runtime/a2ui-root/a2ui-root.js';

/**
 * <canvas-ui> — A2UI rendering surface.
 *
 * Wrapper mode. Wraps an a2ui-root for rendering generated components.
 * Consumer-owns-LLM: fires interaction events, never calls fetch.
 *
 * Events:
 *   canvas-interaction — user interacts with rendered components.
 *     Detail: { type, targetTag, targetId, value }
 */
export class UICanvas extends UIElement {
  static properties = {
    theme: { type: String, default: '', reflect: true },
  };

  static template = () => null;

  #bound = false;
  #rootEl = null;
  #rootContainer = null;
  #history = [];     // P7: version stack (A2UI message arrays)
  #historyIndex = -1;
  static MAX_HISTORY = 10;

  #onKeydown = (e) => {
    if (e.target.closest('input, textarea, [contenteditable]')) return;
    if (!this.contains(document.activeElement) && document.activeElement !== document.body) return;
  };

  #onClick = (e) => {
    if (!this.#rootEl?.contains(e.target)) return;
    this.#emitInteraction('click', e.target);
  };

  #onChange = (e) => {
    if (!this.#rootEl?.contains(e.target)) return;
    this.#emitInteraction('change', e.target);
  };

  #onInput = (e) => {
    if (!this.#rootEl?.contains(e.target)) return;
    this.#emitInteraction('input', e.target);
  };

  #onRetry = (e) => {
    // Re-dispatch as canvas-interaction with type='retry' for uniform handling
    this.dispatchEvent(new CustomEvent('canvas-interaction', {
      bubbles: true,
      detail: {
        type: 'retry',
        targetTag: 'button-ui',
        targetId: 'retry',
        value: '',
        ...e.detail,
      },
    }));
  };

  connected() {
    document.addEventListener('keydown', this.#onKeydown);
    this.addEventListener('click', this.#onClick);
    this.addEventListener('change', this.#onChange);
    this.addEventListener('input', this.#onInput);
    // Forward a2ui-retry from wired error cards so consumers can retry generation
    this.addEventListener('a2ui-retry', this.#onRetry);
  }

  disconnected() {
    document.removeEventListener('keydown', this.#onKeydown);
    this.removeEventListener('click', this.#onClick);
    this.removeEventListener('change', this.#onChange);
    this.removeEventListener('input', this.#onInput);
    this.removeEventListener('a2ui-retry', this.#onRetry);
    this.#rootEl = null;
    this.#rootContainer = null;
    this.#bound = false;
  }

  render() {
    if (this.#bound) return;
    this.#bound = true;

    this.#rootContainer = document.createElement('div');
    this.#rootContainer.setAttribute('data-canvas-surface', '');

    this.#rootEl = document.createElement('a2ui-root');

    if (this.theme) {
      const themeEl = document.createElement('theme-ui');
      themeEl.setAttribute('preset', this.theme);
      themeEl.appendChild(this.#rootEl);
      this.#rootContainer.appendChild(themeEl);
    } else {
      this.#rootContainer.appendChild(this.#rootEl);
    }

    this.appendChild(this.#rootContainer);
  }

  // ── Public API ──

  /** Process a single A2UI message. */
  process(message) {
    this.#rootEl?.process(message);
  }

  /** Process an array of A2UI messages. */
  processAll(messages) {
    if (!this.#rootEl) return;
    for (const msg of messages) this.#rootEl.process(msg);
  }

  /** Reset the canvas. */
  reset() {
    this.#rootEl?.reset();
  }

  /** Return formatted innerHTML of the a2ui-root. */
  getHTML() {
    return this.#rootEl?.innerHTML ?? '';
  }

  /** Snapshot current state to history stack. */
  pushVersion(messages) {
    // Truncate forward history if we're not at the end
    if (this.#historyIndex < this.#history.length - 1) {
      this.#history = this.#history.slice(0, this.#historyIndex + 1);
    }
    this.#history.push(messages ? [...messages] : []);
    if (this.#history.length > UICanvas.MAX_HISTORY) this.#history.shift();
    this.#historyIndex = this.#history.length - 1;
  }

  /** Go back one version. Returns false if already at oldest. */
  back() {
    if (this.#historyIndex <= 0) return false;
    this.#historyIndex--;
    this.#restoreVersion();
    return true;
  }

  /** Go forward one version. Returns false if already at newest. */
  forward() {
    if (this.#historyIndex >= this.#history.length - 1) return false;
    this.#historyIndex++;
    this.#restoreVersion();
    return true;
  }

  get historyLength() { return this.#history.length; }
  get historyIndex() { return this.#historyIndex; }

  #restoreVersion() {
    const messages = this.#history[this.#historyIndex];
    this.#rootEl?.reset();
    if (messages) {
      for (const msg of messages) this.#rootEl?.process(msg);
    }
  }

  // ── Private ──

  #emitInteraction(type, target) {
    this.dispatchEvent(new CustomEvent('canvas-interaction', {
      bubbles: true,
      detail: {
        type,
        targetTag: target.localName,
        targetId: target.id || '',
        value: target.value ?? target.getAttribute('text') ?? '',
      },
    }));
  }
}

customElements.define('canvas-ui', UICanvas);
