/**
 * Copy-to-clipboard button — click writes a value to the clipboard and swaps
 * the button icon to a check for ~1.2s. Self-contained: markup is fully
 * rendered server-side, this component only wires the click handler.
 *
 * Static value (read from the button itself):
 *   <button type="button" data-copy-button data-copy-value="max@acme.com" …>…</button>
 *
 * Live input value (resolved at click-time from the target element's .value):
 *   <button type="button" data-copy-button data-copy-target="privacy_url" …>…</button>
 */
import { resolveHost } from '../core/app-dom.js';

const BUTTON_SELECTOR = '[data-copy-button]';
const DONE_CLASS = 'is-copied';
const DONE_TIMEOUT_MS = 1200;

const copyText = async (value) => {
  if (!value) {return false;}
  if (navigator.clipboard?.writeText) {
    try {
      await navigator.clipboard.writeText(value);
      return true;
    } catch {
      return false;
    }
  }
  const textarea = document.createElement('textarea');
  textarea.value = value;
  textarea.setAttribute('readonly', 'true');
  textarea.style.position = 'fixed';
  textarea.style.opacity = '0';
  document.body.appendChild(textarea);
  textarea.select();
  let ok = false;
  try {
    ok = document.execCommand('copy');
  } catch {
    ok = false;
  }
  document.body.removeChild(textarea);
  return ok;
};

export function initCopyField(root = document, options = {}) {
  const selector = String(options.selector || BUTTON_SELECTOR).trim() || BUTTON_SELECTOR;
  const host = resolveHost(root);
  const buttons = Array.from(host.querySelectorAll(selector));
  if (!buttons.length) {
    return { destroy: () => {} };
  }

  const cleanupFns = [];
  const timers = new Map();

  buttons.forEach((button) => {
    if (!(button instanceof HTMLElement) || button.dataset.copyButtonBound === '1') {
      return;
    }
    button.dataset.copyButtonBound = '1';

    // Clipboard API is unavailable in insecure contexts (http without localhost)
    // and the execCommand fallback is deprecated. If neither is usable, hide
    // the button entirely rather than show a non-functional control.
    const clipboardUsable = typeof navigator.clipboard?.writeText === 'function'
      || typeof document.execCommand === 'function';
    if (!clipboardUsable) {
      button.hidden = true;
      return;
    }

    const onClick = async (event) => {
      event.preventDefault();
      const targetId = (button.dataset.copyTarget || '').trim();
      let value = button.dataset.copyValue || '';
      if (targetId) {
        const target = document.getElementById(targetId);
        if (target && 'value' in target) {
          value = /** @type {HTMLInputElement} */ (target).value;
        }
      }
      const ok = await copyText(value);
      if (!ok) {return;}
      button.classList.add(DONE_CLASS);
      const prevTimer = timers.get(button);
      if (prevTimer) {window.clearTimeout(prevTimer);}
      const timer = window.setTimeout(() => {
        button.classList.remove(DONE_CLASS);
        timers.delete(button);
      }, DONE_TIMEOUT_MS);
      timers.set(button, timer);
    };

    button.addEventListener('click', onClick);
    cleanupFns.push(() => {
      button.removeEventListener('click', onClick);
      delete button.dataset.copyButtonBound;
    });
  });

  const destroy = () => {
    cleanupFns.forEach((fn) => fn());
    timers.forEach((timer) => window.clearTimeout(timer));
    timers.clear();
  };

  return { destroy };
}
