import React, { ComponentType, ReactNode, useEffect } from 'react';
import {
  StyleSheet,
  View,
  ViewStyle,
  ActivityIndicator,
  TextStyle,
} from 'react-native';
import { IWidgetPayload, WidgetKind } from '@livelike/javascript';
import {
  useStyles,
  useLoadWidgetEffect,
  useWidgetDismiss,
  useAnalytics,
} from '../../hooks';
import { ComponentStyleProp, LLComponentStyleFn } from '../../types';
import { LLText } from '../LLText';

export type LLCoreWidgetStyles = {
  widgetContainer: ViewStyle;
  errorText: TextStyle;
};

export type LLCoreWidgetChildrenProps = {
  widget: IWidgetPayload;
  onDismiss?: () => void;
};

export type LLCoreWidgetProps = ComponentStyleProp<LLCoreWidgetStyles> & {
  programId: string;
  widgetId: string;
  widgetKind: WidgetKind;
  LoadingComponent?: ComponentType<unknown>;
  ErrorComponent?: ComponentType<unknown>;
  onDismiss?: () => void;
  children?: (props: LLCoreWidgetChildrenProps) => ReactNode;
};

export function LLCoreWidget({
  programId,
  widgetId,
  widgetKind,
  LoadingComponent,
  ErrorComponent,
  children,
  onDismiss,
  styles: stylesProp,
}: LLCoreWidgetProps) {
  const { dismiss, onDismissHandler } = useWidgetDismiss({
    widgetId,
    onDismiss,
  });
  const { isLoading, error, data } = useLoadWidgetEffect({
    widgetId,
    widgetKind,
    programId,
  });
  const styles = useStyles({
    componentStylesFn: getWidgetStyles,
    stylesProp,
  });
  const widget = data?.[0];
  const { trackEvent } = useAnalytics();
  useEffect(() => {
    if (!isLoading && !error && widget?.id && !dismiss) {
      trackEvent('Widget Displayed', {
        programId,
        widgetId: widget.id,
        widgetKind: widget.kind,
      });
    }
  }, [isLoading, error, widget?.id, widget?.kind, dismiss, trackEvent]);

  if (isLoading) {
    return LoadingComponent ? (
      <LoadingComponent />
    ) : (
      <ActivityIndicator size={'small'} color="blue" />
    );
  }

  if (error) {
    return ErrorComponent ? (
      <ErrorComponent />
    ) : (
      <View style={styles.widgetContainer}>
        <LLText style={styles.errorText}>{'Unable to load widget'}</LLText>
      </View>
    );
  }

  if (!widget || dismiss) {
    return undefined;
  }

  return (
    <View style={styles.widgetContainer}>
      {children?.({
        widget,
        onDismiss: onDismissHandler,
      })}
    </View>
  );
}

const getWidgetStyles: LLComponentStyleFn<LLCoreWidgetStyles> = ({ theme }) =>
  StyleSheet.create({
    widgetContainer: {
      display: 'flex',
      flexDirection: 'column',
      backgroundColor: theme.widgetBackground,
      borderRadius: 4,
      overflow: 'hidden',
    },
    errorText: {
      display: 'flex',
      flex: 1,
      height: 100,
      textAlign: 'center',
      textAlignVertical: 'center',
      color: theme.error,
    },
  });
