import { SyntheticEvent, useEffect, useRef, useState } from 'react';

import { findNodeHandle, Pressable } from 'react-native';
import FastImage, { ImageStyle as FastImageStyle } from 'react-native-fast-image';
import { SvgUri } from 'react-native-svg';

import { useNativeMergeStyles, useStyles } from '@cleartrip/ct-design-style-manager';
import EventCollectorProvider, { useMergeEvents, useTriggerEvents } from '@cleartrip/ct-design-event-propagation';

import { IImageProps } from './type';
import { isSvg } from './style';
import { INativeUIEvent } from '@cleartrip/ct-design-types';
import { isIOS } from '@cleartrip/ct-design-common-utils';

/**
 * Native implementation of `Image`.
 *
 * Migrated from yagami (aldenui) per `Migration.MD`:
 *   - `FastImage` is the raster renderer (RN's built-in `Image`
 *     doesn't cache or decode as well across large lists).
 *   - `.svg` URLs are detected via `isSvg` and delegated to
 *     `react-native-svg`'s `SvgUri`, which `FastImage` can't handle.
 *   - When `onClick` is supplied the tree is wrapped in a
 *     `Pressable` (to get press feedback + hit-slop) inside an
 *     `EventCollectorProvider` so upstream collectors see the tap
 *     through the event-propagation hook chain.
 *
 * No built-in fallback URL is shipped — callers provide their own
 * via the `fallbackUrl` prop when a product default exists.
 */
const Image = ({
  src,
  alt,
  width,
  height,
  fallbackUrl,
  styleConfig,
  onClick,
  onLoad,
  onError,
  resizeMode,
  zoomTransition = false,
}: IImageProps) => {
  const [imageSource, setImageSource] = useState<{ uri: string }>({
    uri: src || fallbackUrl || '',
  });
  const { root: customRootStyles = [] } = styleConfig || {};

  const aspectRatio = customRootStyles.find((style) => style.aspectRatio);

  const nodeElement = useRef<number | null>(null);
  const imageStyles = useStyles(
    () => ({
      image: {
        height: aspectRatio ? {} : height,
        width,
      },
    }),
    [height, width],
  );

  const mergedImageStyles = useNativeMergeStyles(
    [imageStyles.image, ...customRootStyles],
    [imageStyles, customRootStyles],
  );

  const clickWithNodeElement = (e: INativeUIEvent) => {
    if (zoomTransition && nodeElement.current) {
      e.nodeElement = nodeElement.current;
    }
    onClick?.(e);
  };

  const mergedEvents = useMergeEvents({ onClick: clickWithNodeElement ? [clickWithNodeElement] : [] });
  const { onClick: onClickEvent } = useTriggerEvents(mergedEvents);

  useEffect(() => {
    setImageSource({ uri: src || fallbackUrl || '' });
  }, [fallbackUrl, src]);

  // `.svg` URLs go through react-native-svg — FastImage can't decode them.
  if (isSvg(src)) {
    return <SvgUri width={width || 0} height={height || 0} uri={src} style={mergedImageStyles} />;
  }

  const onImageError = () => {
    if (fallbackUrl) {
      setImageSource({ uri: fallbackUrl });
    }
    if (onError) {
      // FastImage's error callback doesn't produce a DOM SyntheticEvent.
      // Synthesize the minimum shape the public API promises so
      // cross-platform consumers don't have to branch.
      const syntheticEvent = {
        currentTarget: {
          src: imageSource.uri,
          onerror: null,
        },
      } as unknown as SyntheticEvent;
      onError(syntheticEvent as never);
    }
  };

  const imageElement = (
    <FastImage
      source={imageSource}
      style={mergedImageStyles as FastImageStyle}
      accessibilityLabel={alt}
      onLoad={onLoad}
      onError={onImageError}
      resizeMode={resizeMode}
    />
  );

  if (!onClick) {
    return imageElement;
  }

  return (
    <EventCollectorProvider value={mergedEvents}>
      <Pressable
        ref={(ref) => {
          if (isIOS()) {
            nodeElement.current = findNodeHandle(ref);
          }
        }}
        style={mergedImageStyles}
        onPress={onClickEvent}
      >
        {imageElement}
      </Pressable>
    </EventCollectorProvider>
  );
};

Image.displayName = 'Image';

export default Image;
