import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faTriangleExclamation,
  faRotateRight,
  faChevronDown,
  faChevronUp,
  faClipboard,
} from "@fortawesome/free-solid-svg-icons";
import { useState, type FC } from "react";

type Variant = "inline" | "card" | "banner";

export type ErrorStateProps = {
  /** Main heading shown to the user */
  title?: string;
  /** Friendly message for the user */
  message?: string;
  /** Raw error to help devs (object, string, whatever) */
  error?: unknown;
  /** Called when user clicks Retry */
  onRetry?: () => Promise<void> | void;
  /** Show a Retry button */
  showRetry?: boolean;
  /** Optional custom icon */
  icon?: IconDefinition;
  /** Visual style */
  variant?: Variant;
  /** Additional actions (e.g. “Report”) */
  actions?: React.ReactNode;
  /** Test id for testing */
  "data-testid"?: string;
  /** ClassName passthrough */
  className?: string;
};

function formatError(err: unknown) {
  if (!err) return "";
  if (typeof err === "string") return err;
  if (err instanceof Error) return err.stack || err.message;
  try {
    return JSON.stringify(err, null, 2);
  } catch {
    return String(err);
  }
}

const baseStyles = "w-full text-left flex items-start gap-3 rounded-md border";

const variants: Record<Variant, string> = {
  inline: "p-3 border-red-200 bg-red-50 text-red-800",
  card: "p-4 border-red-200 bg-red-50 text-red-800 shadow-sm",
  banner: "p-3 border-red-200 bg-red-50 text-red-800 rounded-none border-x-0",
};

export const ErrorState: FC<ErrorStateProps> = ({
  title = "Something went wrong",
  message = "Please try again or contact support if the problem persists.",
  error,
  onRetry,
  showRetry = !!onRetry,
  icon = faTriangleExclamation,
  variant = "inline",
  actions,
  className = "",
  ...rest
}) => {
  const [expanded, setExpanded] = useState(false);
  const [retrying, setRetrying] = useState(false);

  const details = formatError(error);

  async function handleRetry() {
    if (!onRetry) return;
    try {
      setRetrying(true);
      await onRetry();
    } finally {
      setRetrying(false);
    }
  }

  function copyDetails() {
    if (!details) return;
    navigator.clipboard?.writeText(details).catch(() => {});
  }

  return (
    <div
      role="alert"
      aria-live="assertive"
      className={`${baseStyles} ${variants[variant]} ${className}`}
      {...rest}
    >
      <div className="mt-0.5">
        <FontAwesomeIcon icon={icon} className="h-5 w-5" />
      </div>

      <div className="flex-1 space-y-1">
        <h3 className="font-medium">{title}</h3>
        {message && <p className="text-sm opacity-90">{message}</p>}

        {/* Controls */}
        <div className="flex flex-wrap items-center gap-2 pt-1">
          {showRetry && (
            <button
              type="button"
              onClick={handleRetry}
              disabled={retrying}
              className="inline-flex items-center gap-2 px-3 py-1.5 rounded-md bg-red-600 text-white text-sm hover:bg-red-700 disabled:opacity-60"
            >
              <FontAwesomeIcon icon={faRotateRight} className="h-4 w-4" />
              {retrying ? "Retrying…" : "Retry"}
            </button>
          )}

          {details && (
            <>
              <button
                type="button"
                onClick={() => setExpanded((v) => !v)}
                className="inline-flex items-center gap-2 px-3 py-1.5 rounded-md border text-sm hover:bg-white/50"
                aria-expanded={expanded}
                aria-controls="error-details"
              >
                <FontAwesomeIcon
                  icon={expanded ? faChevronUp : faChevronDown}
                  className="h-4 w-4"
                />
                {expanded ? "Hide details" : "Show details"}
              </button>

              <button
                type="button"
                onClick={copyDetails}
                className="inline-flex items-center gap-2 px-3 py-1.5 rounded-md border text-sm hover:bg-white/50"
                aria-label="Copy error details"
              >
                <FontAwesomeIcon icon={faClipboard} className="h-4 w-4" />
                Copy details
              </button>
            </>
          )}

          {actions}
        </div>

        {/* Dev details (collapsible) */}
        {expanded && details && (
          <pre
            id="error-details"
            className="mt-2 max-h-64 overflow-auto text-xs leading-relaxed bg-white/60 text-red-900 border rounded p-3"
          >
            {details}
          </pre>
        )}
      </div>
    </div>
  );
};

export default ErrorState;
