// Copyright © 2022 Olo Inc. All rights reserved.
// This software is made available under the Olo Pay SDK License (See LICENSE.md file)
import React, { useCallback, useImperativeHandle } from 'react';
import { forwardRef, useRef } from 'react';
import {
  HostComponent,
  NativeSyntheticEvent,
  Platform,
  requireNativeComponent,
  StyleSheet,
  View,
} from 'react-native';
import type {
  CardValidationStatus,
  PaymentCardDetailsFormMethods,
  PaymentCardDetailsFormProps,
  PaymentMethod,
} from 'src/definitions';
import type { CardDetailsNativeProps } from 'src/components/definitions/PaymentCardDetailsFormNativeTypes';

import usePaymentCardDetailsFormManager from '../hooks/usePaymentCardDetailsFormManager';

import { sharedComponentStyles } from './styles/sharedStyles';
import { sharedComponentValues } from './definitions/sharedValues';

const CardDetailsNative: HostComponent<CardDetailsNativeProps> =
  requireNativeComponent('PaymentCardDetailsForm');
const ViewManagerMethods = usePaymentCardDetailsFormManager();

export const PaymentCardDetailsForm = forwardRef<
  PaymentCardDetailsFormMethods,
  PaymentCardDetailsFormProps
>(
  (
    {
      cardStyles,
      componentStyles,
      isEnabled,
      onFormComplete,
      viewProps,
      placeholders,
      ...props
    },
    ref: any
  ) => {
    const inputRef = useRef(null);

    const onFormCompleteEventHandler = useCallback(
      (event: NativeSyntheticEvent<CardValidationStatus>) => {
        const cardEvent = event.nativeEvent;

        const formComplete: CardValidationStatus = {
          isValid: cardEvent.isValid,
        };

        onFormComplete?.(formComplete);
      },
      [onFormComplete]
    );

    const createPaymentMethod = async (): Promise<PaymentMethod> => {
      try {
        return await ViewManagerMethods.createPaymentMethod(inputRef);
      } catch (error) {
        throw error;
      }
    };

    const blur = async (): Promise<void> => {
      return await ViewManagerMethods.blur(inputRef);
    };

    const clear = async (): Promise<void> => {
      return await ViewManagerMethods.clear(inputRef);
    };

    const focus = async (): Promise<void> => {
      return await ViewManagerMethods.focus(inputRef);
    };

    useImperativeHandle(ref, () => ({
      blur,
      clear,
      createPaymentMethod,
      focus,
    }));

    return (
      <View style={componentStyles} {...viewProps}>
        <CardDetailsNative
          style={[defaultStyles.cardDetailsForm, cardStyles?.styles]}
          ref={inputRef}
          onFormCompleteEvent={onFormCompleteEventHandler}
          isEnabled={isEnabled}
          placeholders={{
            number:
              placeholders?.number ??
              sharedComponentValues.defaultValues.formNumberPlaceholder,
            expiration:
              placeholders?.expiration ??
              sharedComponentValues.defaultValues.expirationPlaceholder,
            cvv:
              placeholders?.cvv ??
              sharedComponentValues.defaultValues.cvvPlaceholder,
            postalCode:
              placeholders?.postalCode ??
              sharedComponentValues.defaultValues.postalCodePlaceholder,
          }}
          cardStyles={{
            backgroundColor:
              cardStyles?.backgroundColor ??
              sharedComponentStyles.defaultStyles.backgroundColor,
            cursorColor:
              cardStyles?.cursorColor ??
              sharedComponentStyles.defaultStyles.cursorColor,
            // Android Only
            borderColor:
              cardStyles?.borderColor ??
              sharedComponentStyles.defaultStyles.borderColor,
            borderWidth:
              cardStyles?.borderWidth ??
              sharedComponentStyles.defaultStyles.borderWidth,
            cornerRadius:
              cardStyles?.cornerRadius ??
              sharedComponentStyles.defaultStyles.cornerRadius,
            textColor:
              cardStyles?.textColor ??
              sharedComponentStyles.defaultStyles.textColor,
            placeholderColor:
              cardStyles?.placeholderColor ??
              sharedComponentStyles.defaultStyles.placeholderColor,
            fontSize:
              cardStyles?.fontSize ??
              sharedComponentStyles.defaultStyles.fontSize,
            textPaddingLeft:
              cardStyles?.textPaddingLeft ??
              sharedComponentStyles.defaultStyles.paddingLeft,
            textPaddingRight:
              cardStyles?.textPaddingRight ??
              sharedComponentStyles.defaultStyles.paddingRight,
            fieldDividerColor:
              cardStyles?.fieldDividerColor ??
              sharedComponentStyles.defaultStyles.dividerColor,
            fieldDividerWidth:
              cardStyles?.fieldDividerWidth ??
              sharedComponentStyles.defaultStyles.dividerWidth,
            focusedPlaceholderColor:
              cardStyles?.focusedPlaceholderColor ??
              sharedComponentStyles.defaultStyles.focusedPlaceholderColor,
            cardElevation:
              cardStyles?.cardElevation ??
              sharedComponentStyles.defaultStyles.cardElevation,
            fontFamily:
              cardStyles?.fontFamily ??
              sharedComponentStyles.defaultStyles.fontFamily,
            fontWeight:
              cardStyles?.fontWeight ??
              sharedComponentStyles.defaultStyles.fontWeight,
            italic:
              cardStyles?.italic ?? sharedComponentStyles.defaultStyles.italic,
          }}
          {...props}
        />
      </View>
    );
  }
);

const defaultStyles = StyleSheet.create({
  cardDetailsForm: {
    ...Platform.select({
      android: {
        minHeight: 310,
      },
      default: {
        minHeight: 190,
      },
    }),
  },
});
