import { Formik } from "formik";
import { FormikHelpers } from "formik/dist/types";
import React, { useMemo, useState } from "react";
import * as yup from "yup";

import { TipsModuleModal as TipsModuleModalComponent } from "@komi-app/creator-ui";

import { TipsLinkItem } from "../../models/talent/talent-profile-module.model";
import { uploadImageToS3 } from "../../utils/photo";

import { ModuleType } from "@komi-app/shared-types"

export interface InitDataValues {
  src?: string;
  originalFilename?: string;
  platformName?: string;
  placeholder?: {
    title: string,
    link: string,
  }
}
export interface TipsLinkFormValues {
  file?: File;
  src?: string;
  thumbnailSrc?: string;
  title?: string;
  originalFilename?: string;
  link?: string;
}

interface TipsLinkModalProps {
  visible: boolean;
  platform?: Extract<ModuleType, ModuleType.PAYPAL_LINK | ModuleType.VENMO_LINK | ModuleType.CASHAPP_LINK | ModuleType.PATREON_LINK>;
  onChangeVisible: (value: boolean) => void;
  onConfirmCallback: (data: TipsLinkItem) => void;
}

const allowedTypes = ["image/png", "image/jpeg", "image/webp"];

const LINK_VALIDATIONS = {
  [ModuleType.PAYPAL_LINK]: /(https:\/\/)?(www.)?paypal.+\/.+/,
  [ModuleType.VENMO_LINK]: /(https:\/\/)?(www.)?venmo.+\/.+/,
  [ModuleType.CASHAPP_LINK]: /(https:\/\/)?(www.)?cash.(app)(.+)?\/.+/,
  [ModuleType.PATREON_LINK]: /(https:\/\/)?(www.)?patreon.+\/.+/,
}

const TipsLinkModal: React.FC<TipsLinkModalProps> = ({
  visible,
  platform,
  onChangeVisible,
  onConfirmCallback,
}) => {
  const [uploading, setUploading] = useState<boolean>(false);

  const validateSchema = yup.object().shape({
    title: yup.string().required("Enter a title"),
    link: yup.string()
    .required("Enter a link")
    .url("Enter a valid link")
    .matches(platform ? LINK_VALIDATIONS[platform] : /(https:\/\/)?(www.)?.(com)\/.+/,
      "Enter a valid link"
    ),
    src: yup.string().required("Upload an image"),
    file: yup
      .mixed()
      .test({
        message: () => {
          return "File is invalid type, allowed types: png, jpeg, webp";
        },
        test: (value) => {
          if (!value) {
            return true;
          }
  
          return allowedTypes.includes(value.type);
        },
      })
      .test({
        message: ({ value }) => {
          return "Max image size 16 MB";
        },
        test: (value) => {
          if (!value) {
            return true;
          }
  
          return value.size <= 16 * 1024 * 1024;
        },
      }),
  });

  const initData = useMemo<InitDataValues>(()=> {
    switch(platform) {
      case ModuleType.PAYPAL_LINK:
        return {
          src: "https://komi-production-assets.s3.amazonaws.com/photos/tips/PayPal.png",
          originalFilename: "PayPal.png",
          platformName: "PayPal",
          placeholder: {
            title: "Tip me on PayPal",
            link: "https://www.paypal.me/",
          }
        };
      case ModuleType.VENMO_LINK:
        return {
          src: "https://komi-production-assets.s3.amazonaws.com/photos/tips/Venmo.png",
          originalFilename: "Venmo.png",
          platformName: "Venmo",
          placeholder: {
            title: "Tip me on Venmo",
            link: "https://venmo.com/",
          }
        };
      case ModuleType.CASHAPP_LINK:
        return {
          src: "https://komi-production-assets.s3.amazonaws.com/photos/tips/CashApp.png",
          originalFilename: "CashApp.png",
          platformName: "Cash App",
          placeholder: {
            title: "Tip me on CashApp",
            link: "https://cash.app/$",
          }
        };
      case ModuleType.PATREON_LINK:
        return {
          src: "https://komi-production-assets.s3.amazonaws.com/photos/tips/Patreon.png",
          originalFilename: "Patreon.png",
          platformName: "Patreon",
          placeholder: {
            title: "Subscribe to my Patreon",
            link: "https://www.patreon.com/",
          }
        };
      default:
        return {};
    }
  }, [])

  const initialValues = useMemo<TipsLinkFormValues>(() => {
    return {
      originalFilename: initData?.originalFilename,
      src: initData?.src,
      contentType: undefined,
      title: initData?.placeholder?.title,
      link: initData?.placeholder?.link,

    };
  }, []);


  const handleSubmit = async (
    values: TipsLinkFormValues,
    formikHelpers: FormikHelpers<TipsLinkFormValues>,
  ) => {
    const isValid = await validateSchema.isValid(values);

    const { src, file } = values;

    if (!isValid || !src) {
      return;
    }

    const originalFilename = file?.name  || "";
    const contentType = file?.type || "";

    const newItem = {
      src,
      thumbnailSrc: values.thumbnailSrc,
      originalFilename,
      contentType,
      title: values.title,
      url: values.link,
      platform: initData?.platformName,
    };

    onConfirmCallback(newItem);

    formikHelpers.resetForm();
  };

  return (
    <Formik
      initialValues={initialValues}
      onSubmit={handleSubmit}
      validationSchema={validateSchema}
      enableReinitialize
    >
      {(props) => (
        <TipsModuleModalComponent
          heading={`Add ${initData?.platformName} link`}
          onSubmit={props.handleSubmit}
          onCancel={() => {
            onChangeVisible(false);
            props.resetForm();
          }}
          linkLabel={`${initData?.platformName} link`}
          media={
            props.values.src
              ? {
                  src: props.values.thumbnailSrc || props.values.src,
                  name:
                    props.values.file?.name || props.values.originalFilename ||
                    "",
                }
              : undefined
          }
          mediaUploading={uploading}
          disabled={!(props.values?.src && props.values?.title && props.values?.link)}
          onMediaChange={async (file: File | null) => {
            
              // reset field
              props.setFieldValue("file", undefined, true);
              props.setFieldValue("src", undefined, true);

              if (!file) {
                return;
              }

              const validationErrors = await props.setFieldValue(
                "file",
                file,
                true,
              );

              const { file: fileErrors } = validationErrors || {};

              if (fileErrors) {
                props.setFieldValue("file", undefined, false);
                return;
              }

              setUploading(true);

              try {
                props.setFieldValue("originalFilename", file.name, false);
                const url = await uploadImageToS3(file);

                props.setFieldValue("src", url, true);
              } catch (e) {
                props.setFieldError("file", e.message);
              } finally {
                setUploading(false);
              }
          }}
          title={props.values.title}
          onTitleChange={async (title: string) => {
              props.setFieldValue("title", title, true);
          }}
          link={props.values.link}
          onLinkChange={(link: string) => {
            props.setFieldValue("link", link.trim(), true);
          }}
          suggestedAllowedMediaTypes={allowedTypes}
          visible={visible}
          helpers={{
            media: "Max image size 16MB",
          }}
          errors={{
            media: props.errors.file || props.errors.src,
            title: props.errors.title,
            link: props.errors.link,
          }}
        />
      )}
    </Formik>
  );
};

export default TipsLinkModal;
