/**
 * Thin wrapper around React Native's `Image`.
 *
 * Design-system layout (sizes, radii, loading/error UI) is intentionally
 * NOT baked in here — use purpose-built components like `Avatar` instead.
 *
 * What this wrapper adds over a raw RN `Image`:
 *  - Accepts a plain URI **string** as `source` (auto-normalized to `{ uri }`).
 *  - Extends the prop surface with **web-only** HTML attributes (`sizes`,
 *    `loading`, `decoding`, etc.) for better `react-native-web` support.
 *    Props already covered by RN 0.81+ (`alt`, `srcSet`, `crossOrigin`,
 *    `referrerPolicy`) are inherited from the native typings.
 *  - All other props and `ref` are forwarded to the underlying `Image`.
 *
 * Inspired by Expo's html-elements Image primitive:
 * @see https://github.com/expo/expo/blob/main/packages/html-elements/src/primitives/Image.tsx
 */

import { forwardRef, type ComponentPropsWithoutRef, type ComponentRef } from 'react';
import { Image as RNImage, type ImageSourcePropType } from 'react-native';

/** Coerces a plain URI string into the `{ uri }` shape RN expects. */
function normalizeSource(source: string | ImageSourcePropType): ImageSourcePropType {
  if (typeof source === 'string') {
    return { uri: source };
  }
  return source;
}

// ---------------------------------------------------------------------------
// Web-oriented props not yet covered by react-native's Image typings.
// Props already present in RN 0.81+ (alt, srcSet, crossOrigin,
// referrerPolicy) are inherited from the native Image props.
// ---------------------------------------------------------------------------

/**
 * HTML-ish attributes not in RN’s core typings. Forwarded to `Image` with `...props`;
 * **react-native-web** maps supported ones to the DOM `<img>`. On iOS/Android they are
 * typically ignored (no visual effect).
 */
export interface WebImageProps {
  /** DOM `sizes` for responsive selection with `srcSet` — web only. */
  sizes?: string;
  /** DOM lazy-loading hint — web only. */
  loading?: 'lazy' | 'eager';
  /** DOM decode hint — web only. */
  decoding?: 'async' | 'auto' | 'sync';
  /** DOM drag behavior — web only. */
  draggable?: boolean;
  /** DOM focus order — web only. */
  tabIndex?: number;
}

// ---------------------------------------------------------------------------
// ImageProps = native Image props (minus `source`) + WebImageProps + our overrides.
// `source` is re-declared to also accept a plain string.
// ---------------------------------------------------------------------------

export type ImageProps = WebImageProps &
  Omit<ComponentPropsWithoutRef<typeof RNImage>, 'source'> & {
    /** URI string (normalized to `{ uri }`) or standard `ImageSourcePropType`. */
    source: string | ImageSourcePropType;
    className?: string;
  };

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export const Image = forwardRef<ComponentRef<typeof RNImage>, ImageProps>(function Image(
  { source, ...props },
  ref,
) {
  return <RNImage source={normalizeSource(source)} {...props} ref={ref} />;
});

Image.displayName = 'Image';
