import { FC, useMemo, RefObject, IframeHTMLAttributes } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import {
  WebView,
  WebViewProps as ReactNativeWebViewProps,
} from 'react-native-webview';
import { EmbedClientMessages } from '../models/EmbeddedMessageTypes';
import { tryResolveFullIframeUrl } from '../utils/urlResolution';

type WebViewProps = Omit<
  ReactNativeWebViewProps,
  | 'ref'
  | 'onMessage'
  | 'source'
  | 'onFileDownload'
  | 'onShouldStartLoadWithRequest'
>;

type IframeProps = Omit<IframeHTMLAttributes<HTMLIFrameElement>, 'ref' | 'src'>;

export type KomoWebViewProps = {
  /**
   * The URL of the embedded card experience.
   * This can be obtained by querying the embed metadata endpoint.
   */
  embedUrl?: string;

  /**
   * The URL of the authorization endpoint.
   * This can be obtained by querying the embed metadata endpoint.
   * If this is provided, the experience modal will first load the auth URL, and then redirect to the embed URL.
   */
  embedAuthUrl?: string;

  /**
   * The passthrough parameters to add to the auth URL.
   * These will be added to the auth URL as query parameters.
   * For example, an auth0 session transfer token can be added to the auth URL as a passthrough parameter.
   */
  authPassthroughParams?: URLSearchParams;

  /**
   * Prefill values for the form within the experience.
   */
  formPrefillValues?: Record<string, string>;

  /**
   * Extension data values for the experience.
   */
  extensionDataValues?: Record<string, string | number | boolean | object>;

  /**
   * Additional props for the iframe component.
   * Only applies if the platform is web.
   */
  iframeProps?: IframeProps;

  /**
   * Additional props for the react-native-webview component.
   * Only applies if the platform is not web.
   */
  webViewProps?: WebViewProps;

  /**
   * Callback for when a file download is requested.
   * Only applies to iOS. See react-native-webview docs for more details.
   */
  onFileDownload?: ReactNativeWebViewProps['onFileDownload'];

  iframeRef?: RefObject<HTMLIFrameElement | null>;
  webviewRef?: RefObject<WebView | null>;

  isLoading?: boolean;
  onMessage: (data: EmbedClientMessages) => void;
};


export const KomoWebView: FC<KomoWebViewProps> = ({
  embedUrl,
  embedAuthUrl,
  authPassthroughParams,
  formPrefillValues,
  extensionDataValues,
  iframeProps,
  webViewProps,
  onFileDownload,
  iframeRef,
  webviewRef,
  isLoading,
  onMessage,
}) => {
  const iframeUrl = useMemo<string | undefined>(
    () =>
      // Load the webview with the initial iframe url
      tryResolveFullIframeUrl(
        embedUrl,
        embedAuthUrl,
        authPassthroughParams,
        formPrefillValues,
        extensionDataValues
      ),
    // We only want the initial iframe URL to be calculated once per modal open.
    []
  );

  return (
    <View style={styles.webviewContainer}>
      {Platform.OS === 'web' ? (
        <iframe
          src={iframeUrl}
          height="100%"
          width="100%"
          frameBorder="0"
          allowFullScreen
          allow="clipboard-write; camera;"
          loading="lazy"
          ref={iframeRef}
          {...iframeProps}
          style={{
            ...(isLoading ? styles.iframeLoading : styles.iframeLoaded),
            ...(iframeProps?.style ? iframeProps.style : {}),
          }}
        />
      ) : (
        <WebView
          ref={webviewRef}
          allowsInlineMediaPlayback={true}
          source={{
            uri: iframeUrl || '',
          }}
          onMessage={(e) => {
            try {
              const data = JSON.parse(e.nativeEvent.data);
              onMessage(data);
            } catch (error) {
              console.error(error);
            }
          }}
          onFileDownload={onFileDownload}
          {...webViewProps}
          style={[
            styles.webview,
            isLoading ? styles.iframeLoading : styles.iframeLoaded,
            ...(webViewProps?.style ? [webViewProps.style] : []),
          ]}
        />
      )}
    </View>
  );
};


const styles = StyleSheet.create({
  webviewContainer: {
    width: '100%',
    flex: 1,
  },
  webview: {
    backgroundColor: 'transparent',
  },
  iframeLoading: {
    opacity: 0,
  },
  iframeLoaded: {
    opacity: 1,
  },
});