import { useEffect, useRef, useState, type MouseEvent } from "react";
import { Check, Copy } from "lucide-react";
import { truncateMiddle } from "../lib/format";

/**
 * Renders a long identifier (URI / hash / id) truncated with an always-available
 * copy button. The full value is exposed via the `title` attribute.
 */
export function CopyableValue({
  value,
  max = 36,
  label = "value",
}: {
  value: string | null | undefined;
  /** Max rendered characters before middle-truncation. */
  max?: number;
  /** Accessible description of what is copied, e.g. "object URI". */
  label?: string;
}) {
  const [copied, setCopied] = useState(false);
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

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

  if (!value) return <span className="text-faint">—</span>;

  const onCopy = async (event: MouseEvent) => {
    // Don't trigger row-level click handlers (navigation) when copying.
    event.stopPropagation();
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      if (timer.current) clearTimeout(timer.current);
      timer.current = setTimeout(() => setCopied(false), 1500);
    } catch {
      // Clipboard API unavailable (permissions, non-secure context) — select
      // fallback is intentionally omitted; the title attribute exposes the
      // full value for manual copying.
      setCopied(false);
    }
  };

  return (
    <span className="copyable" title={value}>
      <span className="copyable-text">{truncateMiddle(value, max)}</span>
      <button
        type="button"
        className={`copy-btn${copied ? " copied" : ""}`}
        onClick={onCopy}
        aria-label={`Copy ${label}`}
        aria-live="polite"
      >
        {copied ? <Check size={13} aria-hidden="true" /> : <Copy size={13} aria-hidden="true" />}
      </button>
    </span>
  );
}
