---
// CopyPrompt — copy-to-clipboard island for full-guide. One per button.
//
// Click reads `#${target}`'s textContent, copies it via
// `navigator.clipboard.writeText`, and falls back to a `document.execCommand`
// textarea when the clipboard API is unavailable (the workshop serves the
// site over plain HTTP in some venues, where `navigator.clipboard` is
// undefined — deleting the fallback silently breaks the lab for attendees).
// Both paths are kept on purpose; this is the contract the legacy app.js
// copyPrompt function uses for the three full-guide prompts.
//
// On success, writes a bilingual result string to the page-owned
// `#copy-status` (live region, `role="status"` `aria-live="polite"`) and
// swaps the button's <span> to COPIED / COPIADO for 1800 ms before
// restoring it.
//
// Language comes from `document.documentElement.lang` — set today by
// app.js's `applyLanguage` and tomorrow by task 15c's language-toggle
// island. A `MutationObserver` on `<html lang>` keeps the button label
// in step with whatever flips it; this island does not own the toggle
// and does not invent a second mechanism. Task 15c and 15d should align
// on this — see the task report.

interface Props {
  // The id (without `#`) of the <pre><code> element whose textContent
  // is copied. Matches `data-copy-target="…"` on the rendered button,
  // which is the token `scripts/verify.mjs` asserts in the legacy
  // `full-guide/index.html`.
  target: 'prompt-install-skills' | 'prompt-basic' | 'prompt-skills' | string;
}

const { target } = Astro.props;
---

<button class="copy-prompt-button" data-copy-target={target} data-copy-prompt-button type="button">
  <span data-copy-prompt-label>COPY</span>
  <i aria-hidden="true">↗</i>
</button>

<script is:inline>
  // CopyPrompt island — click handler.
  // Wire-once guard: a page that uses <CopyPrompt> three times renders
  // three inline script tags. Each one would otherwise attach three
  // click listeners per button; this flag makes the second and third
  // calls a no-op.
  (function () {
    if (window.__copyPromptWired) return;
    window.__copyPromptWired = true;

    const STRINGS = {
      en: {
        button: 'COPY',
        copied: 'COPIED',
        success: 'Prompt copied. Paste it into a fresh agent session.',
        failure: 'Copy unavailable. Select the text manually.',
      },
      pt: {
        button: 'COPIAR',
        copied: 'COPIADO',
        success: 'Prompt copiado. Cole em uma nova sessão de agente.',
        failure: 'Não foi possível copiar. Selecione o texto manualmente.',
      },
    };

    function currentLang() {
      return document.documentElement.lang === 'pt-BR' ? 'pt' : 'en';
    }

    function labels() {
      return STRINGS[currentLang()];
    }

    function setStatus(copied) {
      const status = document.querySelector('#copy-status');
      if (!status) return;
      const l = labels();
      status.textContent = copied ? l.success : l.failure;
    }

    function fallbackCopy(value) {
      // The textarea dance is straight from the legacy app.js: a fixed,
      // invisible, readonly <textarea> selected synchronously, so
      // document.execCommand('copy') sees a real selection. Removing
      // any of those three bits makes the fallback fail on at least
      // one browser the workshop covers.
      const helper = document.createElement('textarea');
      helper.value = value;
      helper.setAttribute('readonly', '');
      helper.style.position = 'fixed';
      helper.style.opacity = '0';
      document.body.appendChild(helper);
      helper.select();
      let copied = false;
      try {
        copied = document.execCommand('copy');
      } catch {
        copied = false;
      }
      helper.remove();
      return copied;
    }

    function onResult(button, copied) {
      setStatus(copied);
      if (!copied) return;
      const l = labels();
      const span = button.querySelector('span');
      if (span) span.textContent = l.copied;
      button.classList.add('copied');
      // 1800ms matches the legacy copyPrompt. Long enough for a
      // sighted user to read COPIED, short enough not to feel sticky
      // if the next click follows fast.
      window.setTimeout(function () {
        button.classList.remove('copied');
        if (span) span.textContent = labels().button;
      }, 1800);
    }

    function copyPrompt(button) {
      const id = button.dataset.copyTarget;
      if (!id) return;
      const target = document.querySelector('#' + id);
      if (!target) return;
      const visible = target.querySelector(':scope > [data-language-content]:not([hidden])');
      const value = visible?.textContent || target.textContent || '';

      if (
        typeof navigator !== 'undefined' &&
        navigator.clipboard &&
        typeof navigator.clipboard.writeText === 'function'
      ) {
        // navigator.clipboard.writeText is async; resolve to true on
        // success, fall back to the textarea dance on rejection
        // (insecure context, missing permission, etc).
        navigator.clipboard.writeText(value).then(
          function () {
            onResult(button, true);
          },
          function () {
            onResult(button, fallbackCopy(value));
          },
        );
        return;
      }
      onResult(button, fallbackCopy(value));
    }

    function syncLabels() {
      const l = labels();
      const buttons = document.querySelectorAll('[data-copy-prompt-button]');
      for (let i = 0; i < buttons.length; i++) {
        const btn = buttons[i];
        // Mid-feedback buttons (1800ms COPIED state) keep their
        // swapped label until the timer fires; otherwise the toggle
        // would visibly flicker the COPIED text back to the default.
        if (btn.classList.contains('copied')) continue;
        const span = btn.querySelector('span');
        if (span) span.textContent = l.button;
      }
    }

    const buttons = document.querySelectorAll('[data-copy-prompt-button]');
    for (let i = 0; i < buttons.length; i++) {
      buttons[i].addEventListener(
        'click',
        (function (button) {
          return function () {
            copyPrompt(button);
          };
        })(buttons[i]),
      );
    }

    // Pick up external language changes (task 15c's toggle) without
    // owning the toggle itself. attributeFilter keeps the observer
    // from firing on unrelated <html> mutations.
    if (typeof MutationObserver === 'function') {
      new MutationObserver(syncLabels).observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['lang'],
      });
    }
    // Sync on first hydrate so a page rendered server-side as English
    // picks up the user's stored PT preference without waiting for a
    // click. app.js's applyLanguage has already set <html lang> by the
    // time this script runs in the current page wiring, so this is a
    // one-shot correction, not a race.
    syncLabels();
  })();
</script>

<style>
  /* Component-scoped. The legacy full-guide/styles.css carries the
     full visual treatment (button border, hover, `.copied` state,
     etc.); 15d ports that wholesale when it migrates the page. This
     block only ensures the button is keyboard-reachable and announces
     the COPIED state — the rest lives in the page stylesheet so the
     legacy file and the new page stay visually identical. */
  .copy-prompt-button {
    cursor: pointer;
  }
  .copy-prompt-button:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
  }
</style>
