"use client";

/**
 * Figma: "Asset / Avatar" (18628:32840). Circular (or rounded-square) image
 * with initials or a person mark when `src` is missing or fails to load.
 */

import { memo, useLayoutEffect, useRef, useState } from "react";
import type {
  AvatarShapeValue,
  AvatarSizeValue,
  AvatarVariantValue,
} from "../../../../lib/propNormalization";

export type { AvatarShapeValue, AvatarSizeValue, AvatarVariantValue };

export interface AvatarProps {
  src?: string;
  alt: string;
  size?: AvatarSizeValue;
  /** 1–2 characters, or a name (first letters of the first two words). */
  initials?: string;
  shape?: AvatarShapeValue;
  /** Fallback chrome: cream fill (default) or yellow outline. */
  variant?: AvatarVariantValue;
  className?: string;
  onClick?: () => void;
}

const SIZE_CLASS: Record<AvatarSizeValue, string> = {
  small:
    "h-[var(--spacing-scale-016)] w-[var(--spacing-scale-016)] text-xx-small-label",
  medium:
    "h-[var(--spacing-scale-018)] w-[var(--spacing-scale-018)] text-xx-small-label",
  large:
    "h-[var(--spacing-scale-024)] w-[var(--spacing-scale-024)] text-xx-small-label",
  xlarge:
    "h-[var(--spacing-scale-032)] w-[var(--spacing-scale-032)] text-x-small-label",
};

function formatAvatarInitials(value: string): string {
  const trimmed = value.trim();
  if (!trimmed) return "";
  const words = trimmed.split(/\s+/);
  if (words.length >= 2) {
    return `${words[0]?.[0] ?? ""}${words[1]?.[0] ?? ""}`.toUpperCase();
  }
  return trimmed.slice(0, 2).toUpperCase();
}

function AvatarPersonIcon() {
  return (
    <svg
      viewBox="0 0 24 24"
      className="h-1/2 w-1/2"
      aria-hidden
      focusable="false"
    >
      <path
        fill="currentColor"
        d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8V21h19.2v-1.8c0-3.2-6.4-4.8-9.6-4.8z"
      />
    </svg>
  );
}

const Avatar = memo<AvatarProps>(
  ({
    src,
    alt,
    size = "small",
    initials,
    shape = "circle",
    variant = "filled",
    className = "",
    onClick,
  }) => {
    const imgRef = useRef<HTMLImageElement>(null);
    const [failed, setFailed] = useState(false);
    const [loaded, setLoaded] = useState(false);
    const trimmedSrc = src?.trim() ?? "";
    const hasSrc = trimmedSrc.length > 0;
    const showImage = hasSrc && !failed;
    const mark = initials ? formatAvatarInitials(initials) : "";
    const decorative = alt.trim().length === 0;

    useLayoutEffect(() => {
      setFailed(false);
      const img = imgRef.current;
      setLoaded(Boolean(img?.complete && img.naturalWidth > 0));
    }, [trimmedSrc]);

    const radiusClass =
      shape === "rounded-square"
        ? "rounded-[var(--measures-radius-200,8px)]"
        : "rounded-[var(--radius-measures-radius-full)]";
    const fallbackChrome =
      variant === "outlined"
        ? "border-[1.5px] border-solid border-[var(--color-content-default-brand-primary)] bg-transparent text-[var(--color-content-default-brand-primary)]"
        : "bg-[var(--color-surface-invert-brand-primary)] text-[var(--color-content-default-primary)]";
    // White 30% ring on small photos: no DS token (opacity scale is black-alpha).
    const smallImageBorder =
      size === "small" && showImage && loaded
        ? "border-[1.5px] border-solid border-[#FFFFFF4D]"
        : "";
    const interactiveClass = onClick
      ? `cursor-pointer appearance-none bg-transparent p-0 ${smallImageBorder ? "" : "border-0"} transition-opacity hover:opacity-90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-border-invert-primary)]`
      : "";
    const shellClass =
      `relative inline-flex box-border shrink-0 items-center justify-center overflow-hidden ${SIZE_CLASS[size]} ${radiusClass} ${smallImageBorder} ${interactiveClass} ${className}`.trim();

    const showFallback = !showImage;
    const showSkeleton = showImage && !loaded;

    const visual = (
      <>
        {showFallback ? (
          <span
            className={`absolute inset-0 flex items-center justify-center font-medium ${fallbackChrome} ${radiusClass}`}
          >
            {mark ? mark : <AvatarPersonIcon />}
          </span>
        ) : null}
        {showSkeleton ? (
          <span
            className={`absolute inset-0 animate-pulse bg-[var(--color-surface-default-tertiary)] ${radiusClass}`}
            aria-hidden
          />
        ) : null}
        {showImage ? (
          /* eslint-disable-next-line @next/next/no-img-element -- avatar image from URL */
          <img
            ref={imgRef}
            src={trimmedSrc}
            alt={onClick ? "" : alt}
            className={`relative z-[1] h-full w-full object-cover ${radiusClass} ${loaded ? "opacity-100" : "opacity-0"}`}
            loading="eager"
            decoding="async"
            fetchPriority="high"
            onLoad={() => setLoaded(true)}
            onError={() => {
              setFailed(true);
              setLoaded(false);
            }}
          />
        ) : null}
      </>
    );

    if (onClick) {
      return (
        <button
          type="button"
          data-figma-node="18628-32840"
          className={shellClass}
          onClick={onClick}
          aria-label={decorative ? undefined : alt}
        >
          {visual}
        </button>
      );
    }

    return (
      <span
        data-figma-node="18628-32840"
        className={shellClass}
        {...(showFallback
          ? decorative
            ? { "aria-hidden": true as const }
            : { role: "img" as const, "aria-label": alt }
          : {})}
      >
        {visual}
      </span>
    );
  },
);

Avatar.displayName = "Avatar";

export default Avatar;
