// Copy text to the clipboard, robust across iOS Safari and non-secure origins.
//
// The synchronous `execCommand("copy")` path (a hidden, selected textarea) is the
// battle-tested, user-gesture-safe primitive: it works on iOS Safari and every
// desktop browser. We run it FIRST, inside the click gesture, before any `await`
// can spend the page's transient user activation — awaiting a rejected async
// `navigator.clipboard.writeText` first is exactly what makes the fallback fail on
// iOS. Only if the sync path fails (some sandboxed / permission-locked contexts
// disable execCommand) do we fall back to the async Clipboard API. Returns true on
// success so callers can toast.
export async function copyText(text: string): Promise<boolean> {
  if (legacyCopy(text)) return true;
  if (navigator.clipboard?.writeText) {
    try {
      await navigator.clipboard.writeText(text);
      return true;
    } catch {
      // both paths failed
    }
  }
  return false;
}

function legacyCopy(text: string): boolean {
  const active = document.activeElement as HTMLElement | null;
  // Preserve any text the user had selected on the page — focusing our textarea
  // collapses it, so snapshot the range and restore it afterwards.
  const sel = document.getSelection();
  const savedRange = sel && sel.rangeCount ? sel.getRangeAt(0) : null;
  const ta = document.createElement("textarea");
  ta.value = text;
  ta.setAttribute("readonly", ""); // suppress the iOS keyboard
  // Hidden but still selectable: iOS won't copy from `display:none`/`opacity:0`, so
  // clip it out of view while keeping a live, user-selectable node.
  ta.style.position = "fixed";
  ta.style.top = "0";
  ta.style.left = "0";
  ta.style.width = "1px";
  ta.style.height = "1px";
  ta.style.padding = "0";
  ta.style.border = "none";
  ta.style.clip = "rect(0, 0, 0, 0)";
  ta.style.userSelect = "text";
  ta.style.setProperty("-webkit-user-select", "text");
  document.body.appendChild(ta);
  try {
    ta.focus();
    ta.select();
    ta.setSelectionRange(0, text.length); // iOS needs an explicit range
    return document.execCommand("copy");
  } catch {
    return false;
  } finally {
    document.body.removeChild(ta);
    active?.focus?.(); // restore focus we borrowed for the copy
    if (savedRange) {
      sel!.removeAllRanges();
      sel!.addRange(savedRange);
    }
  }
}
