"use client";

import { useEffect, useRef, useState } from "react";

interface Props {
  text: string;
  /** Visible label, e.g. "Copy program". Pass empty string to render
   * icon-only (the visually-hidden `aria-label` still applies). */
  label?: string;
  ariaLabel?: string;
  /** "default" = full bordered button with label; "icon" = compact
   * icon-only (for inside tiles). */
  variant?: "default" | "icon";
  /** Optional className override. */
  className?: string;
  /** Click handler for the host to know a copy happened (e.g. analytics
   * or downstream UI). */
  onCopied?: () => void;
}

/**
 * Reusable copy-to-clipboard button.
 *
 * Uses ``navigator.clipboard.writeText`` when available; degrades to a
 * hidden ``<textarea>`` + ``document.execCommand("copy")`` fallback when
 * the page isn't served over a secure context.
 *
 * Shows a brief "Copied" affordance after a successful copy.
 */
export default function CopyButton({
  text,
  label = "Copy",
  ariaLabel,
  variant = "default",
  className,
  onCopied,
}: Props) {
  const [copied, setCopied] = useState(false);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
    };
  }, []);

  async function copy(e: React.MouseEvent) {
    e.stopPropagation();
    e.preventDefault();
    let ok = false;
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text);
        ok = true;
      } else {
        ok = legacyCopy(text);
      }
    } catch {
      ok = legacyCopy(text);
    }
    if (ok) {
      setCopied(true);
      if (timerRef.current) clearTimeout(timerRef.current);
      timerRef.current = setTimeout(() => setCopied(false), 1400);
      onCopied?.();
    }
  }

  if (variant === "icon") {
    return (
      <button
        type="button"
        onClick={copy}
        aria-label={ariaLabel ?? "Copy program text"}
        title={copied ? "Copied" : "Copy program text"}
        className={
          className ??
          "inline-flex h-5 w-5 items-center justify-center rounded text-muted hover:text-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-accent"
        }
      >
        {copied ? <CheckGlyph /> : <CopyGlyph />}
      </button>
    );
  }

  return (
    <button
      type="button"
      onClick={copy}
      aria-label={ariaLabel ?? label}
      className={
        className ??
        "inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 text-[11px] font-medium text-ink hover:border-accent hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
      }
    >
      {copied ? <CheckGlyph /> : <CopyGlyph />}
      <span>{copied ? "Copied" : label}</span>
    </button>
  );
}

function CopyGlyph() {
  return (
    <svg
      aria-hidden
      width="12"
      height="12"
      viewBox="0 0 16 16"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.4"
    >
      <rect x="5" y="3" width="9" height="11" rx="1.5" />
      <path d="M3 11.5V3.5A1.5 1.5 0 0 1 4.5 2H11" />
    </svg>
  );
}

function CheckGlyph() {
  return (
    <svg
      aria-hidden
      width="12"
      height="12"
      viewBox="0 0 16 16"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.6"
    >
      <path d="M3 8.5L6.5 12L13 5" />
    </svg>
  );
}

function legacyCopy(text: string): boolean {
  try {
    const ta = document.createElement("textarea");
    ta.value = text;
    ta.setAttribute("readonly", "");
    ta.style.position = "fixed";
    ta.style.opacity = "0";
    document.body.appendChild(ta);
    ta.select();
    const ok = document.execCommand("copy");
    document.body.removeChild(ta);
    return ok;
  } catch {
    return false;
  }
}
