// @design-system: domain/AvatarUploadButton

/**
 * AvatarUploadButton — circular button that shows an avatar image (via the
 * shared Image primitive) or a User icon fallback, and triggers a hidden file
 * input on click so the user can upload a new avatar.
 *
 * A11y:
 * - Root is a `<button>` with an i18n aria-label.
 * - Hidden `<input type="file">` is sr-only; its label is announced by AT.
 * - Camera overlay is aria-hidden (decorative affordance).
 * - Focus ring always visible.
 * - Respects `prefers-reduced-motion` on the overlay transition.
 *
 * @example
 * <AvatarUploadButton
 *   src={avatarSrc}
 *   alt={profile.displayName}
 *   onChange={(file) => handleAvatarChange(file)}
 * />
 */

'use client';

import { useRef } from 'react';
import { cn } from '@/lib/cn';
import { Image } from '@/components/ui/primitives/Image';
import { Icon } from '@/components/ui/icons/Icon';
import { useT } from '@/lib/i18n/react';

export interface AvatarUploadButtonProps {
  /** R2 key or absolute URL for the current avatar. When absent, shows User icon fallback. */
  src?: string;
  /** Accessible description of the avatar image. REQUIRED. */
  alt: string;
  /** Called with the selected File after the user picks one. */
  onChange: (file: File) => void;
  /**
   * Diameter of the circular button in px.
   * @default 64
   */
  size?: number;
  /** When true, `src` is a ready-to-use absolute URL (e.g. gravatar) rendered as a
   *  plain <img>, bypassing the R2 variant pipeline. */
  external?: boolean;
  /** When true, the button is non-interactive and visually muted. */
  disabled?: boolean;
  className?: string;
}

export function AvatarUploadButton({
  src,
  alt,
  onChange,
  size = 64,
  external = false,
  disabled = false,
  className,
}: AvatarUploadButtonProps) {
  const t = useT('avatar_upload_button');
  const inputRef = useRef<HTMLInputElement>(null);

  function handleClick() {
    if (!disabled) inputRef.current?.click();
  }

  function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (file) onChange(file);
    // Reset so same file can be re-selected if needed
    e.target.value = '';
  }

  return (
    <>
      <button
        type="button"
        aria-label={t('change_avatar')}
        onClick={handleClick}
        disabled={disabled}
        style={{ width: size, height: size }}
        className={cn(
          'relative shrink-0 overflow-hidden rounded-full',
          'bg-surface-inset',
          'flex items-center justify-center',
          'focus-visible:ring-brand-primary-500 focus-visible:outline-none focus-visible:ring-2',
          disabled && 'cursor-not-allowed opacity-50',
          className,
        )}
      >
        {src && external ? (
          // External absolute URL (gravatar) — plain <img>, not the R2 variant pipeline.
          <img
            src={src}
            alt={alt}
            width={size}
            height={size}
            className="h-full w-full object-cover"
          />
        ) : src ? (
          <Image
            src={src}
            alt={alt}
            width={size}
            height={size}
            variant="thumb"
            loading="eager"
            className="h-full w-full object-cover"
          />
        ) : (
          <Icon name="User" size="lg" className="text-text-muted" aria-hidden />
        )}

        {/* Camera overlay — visible on hover/focus, decorative */}
        {!disabled && (
          <span
            aria-hidden="true"
            className={cn(
              'absolute inset-0 flex items-center justify-center rounded-full',
              'bg-surface-overlay opacity-0 transition-opacity',
              'motion-safe:transition-opacity',
              'hover:opacity-100 group-focus-visible:opacity-100',
            )}
          >
            <Icon name="Camera" size="md" className="text-text-inverse" aria-hidden />
          </span>
        )}
      </button>

      {/* Hidden file input — sr-only, not in tab order */}
      <input
        ref={inputRef}
        type="file"
        accept="image/*"
        aria-label={t('file_input')}
        className="sr-only"
        tabIndex={-1}
        onChange={handleFileChange}
        disabled={disabled}
      />
    </>
  );
}
