/**
 * Non-side-effect class export for `<agent-feedback-bar-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/agent-feedback-bar`
 * (which imports this file + calls `defineIfFree()`).
 *
 * @see ../../USAGE.md#registration--auto-vs-explicit
 */

/**
 * <agent-feedback-bar-ui> — Thumbs + save row under an agent response.
 *
 * Emits semantic events; the host decides how to persist. Status slot shows a
 * short acknowledgement ("Thanks!", "Saved as X") after an action fires.
 *
 * Usage:
 *   <agent-feedback-bar-ui
 *     save-label="Save pattern"
 *     save-icon="bookmark-simple"
 *   ></agent-feedback-bar-ui>
 *
 *   el.addEventListener('feedback-rate', e => persist(e.detail.rating));
 *   el.addEventListener('feedback-save', async () => {
 *     const name = await savePattern(...);
 *     el.setStatus(`Saved as "${name}"`, { lock: 'save' });
 *   });
 *
 * Attributes:
 *   save-label  — text of the save button (empty → save button hidden)
 *   save-icon   — icon for the save button (default: bookmark-simple)
 *   disabled    — disable all actions
 *
 * Events:
 *   feedback-rate  — detail: { rating: 1..5 }  (thumbs-up = 5, thumbs-down = 2)
 *   feedback-save  — detail: {}                (save action pressed)
 *
 * JS API:
 *   .setStatus(text, { lock? })  lock='rate'|'save'|'all' disables matching buttons
 *   .reset()                      clear status, re-enable buttons
 */

import { UIElement } from '../../core/element.js';

function makeButton({ icon, text = '', title = '' }) {
  const btn = document.createElement('button-ui');
  btn.setAttribute('icon', icon);
  btn.setAttribute('variant', 'ghost');
  btn.setAttribute('size', 'sm');
  if (text) btn.setAttribute('text', text);
  // §190a (v0.5.6): supply title= for icon-only buttons. button-ui's §184
  // FEEDBACK-08 §8 a11y safety-net mirrors title → aria-label automatically
  // when the button is icon-only. Closes the per-render console.warn class
  // captured 2026-05-14 ("Icon-only button is missing an accessible name").
  if (!text && title) btn.setAttribute('title', title);
  return btn;
}

export class UIAgentFeedbackBar extends UIElement {
  static properties = {
    saveLabel: { type: String,  default: '',                reflect: true, attribute: 'save-label' },
    saveIcon:  { type: String,  default: 'bookmark-simple', reflect: true, attribute: 'save-icon' },
    disabled:  { type: Boolean, default: false, reflect: true },
  };

  static template = () => null;

  #upEl = null;
  #downEl = null;
  #saveEl = null;
  #statusEl = null;
  #rated = false;
  #saved = false;

  connected() {
    this.#build();
  }

  disconnected() {
    this.#upEl?.removeEventListener('press', this.#onUp);
    this.#downEl?.removeEventListener('press', this.#onDown);
    this.#saveEl?.removeEventListener('press', this.#onSave);
    this.#upEl = this.#downEl = this.#saveEl = this.#statusEl = null;
  }

  setStatus(text, { lock = '' } = {}) {
    if (!this.#statusEl) return;
    this.#statusEl.textContent = text || '';
    if (lock === 'rate' || lock === 'all') {
      this.#rated = true;
      if (this.#upEl) this.#upEl.disabled = true;
      if (this.#downEl) this.#downEl.disabled = true;
    }
    if (lock === 'save' || lock === 'all') {
      this.#saved = true;
      if (this.#saveEl) this.#saveEl.disabled = true;
    }
  }

  reset() {
    this.#rated = false;
    this.#saved = false;
    if (this.#statusEl) this.#statusEl.textContent = '';
    if (this.#upEl) this.#upEl.disabled = false;
    if (this.#downEl) this.#downEl.disabled = false;
    if (this.#saveEl) this.#saveEl.disabled = false;
  }

  #onUp   = () => { if (!this.#rated && !this.disabled) this.#emitRate(5); };
  #onDown = () => { if (!this.#rated && !this.disabled) this.#emitRate(2); };
  #onSave = () => { if (!this.#saved && !this.disabled) this.#emitSave(); };

  #emitRate(rating) {
    this.dispatchEvent(new CustomEvent('feedback-rate', {
      bubbles: true, detail: { rating },
    }));
    // Host owns lock — but pre-set a generic ack as a courtesy.
    if (!this.#statusEl?.textContent) {
      this.setStatus(rating >= 4 ? 'Thanks!' : 'Noted', { lock: 'rate' });
    }
  }

  #emitSave() {
    this.dispatchEvent(new CustomEvent('feedback-save', {
      bubbles: true, detail: {},
    }));
  }

  render() {
    // Re-sync attributes (label/icon) that may have changed.
    const label = this.saveLabel;
    const icon = this.saveIcon;
    if (this.#saveEl) {
      if (label) {
        this.#saveEl.setAttribute('text', label);
        this.#saveEl.hidden = false;
      } else {
        this.#saveEl.hidden = true;
      }
      if (icon) this.#saveEl.setAttribute('icon', icon);
    }
  }

  #build() {
    this.innerHTML = '';

    this.#upEl = makeButton({ icon: 'thumbs-up', title: 'Rate this response positively' });
    this.#downEl = makeButton({ icon: 'thumbs-down', title: 'Rate this response negatively' });
    this.#saveEl = makeButton({
      icon: this.saveIcon || 'bookmark-simple',
      text: this.saveLabel || '',
      title: this.saveLabel ? '' : 'Save this response',
    });
    if (!this.saveLabel) this.#saveEl.hidden = true;

    this.#upEl.addEventListener('press', this.#onUp);
    this.#downEl.addEventListener('press', this.#onDown);
    this.#saveEl.addEventListener('press', this.#onSave);

    this.#statusEl = document.createElement('span');
    this.#statusEl.setAttribute('data-feedback-status', '');

    this.append(this.#upEl, this.#downEl, this.#saveEl, this.#statusEl);
  }
}
