import "./ProfilePhoto.scss";
import { Button, Col, Row, Upload } from "antd";
import { UploadFile } from "antd/lib/upload/interface";
import React, { useCallback, useEffect, useState, useRef } from "react";
import { useDispatch } from "react-redux";
import { MediaUpload } from "redux/Common/types";
import { useTypedSelector } from "redux/rootReducer";
import { setTalentProfileAction } from "redux/User/actions";
import { selectUserData, selectIsAutoSaveSuccess } from "redux/User/selector";
import { User } from "redux/User/types";
import { onBeforeUpload, pushImageToS3, uploadImageToS3 } from "utils/photo";
import ProfileImageCropUpload from "components/ProfileImageCrop/Upload";
import ProfileImageCropUpdate from "components/ProfileImageCrop/Update";
import { Paragraph, Text } from "components/Typography";
import { Icon } from "components/Icon";
import Progress from "components/Progress";
import ProfilePhotoLoading from "./ProfilePhotoLoading";
import notification from "../../../../utils/notification";
import { loadImage } from "../../../../utils/image";
import { RcFile } from "antd/lib/upload";
import { LazyLoadImage } from "react-lazy-load-image-component";
import config from "config";
import "react-lazy-load-image-component/src/effects/blur.css";
import { FLAGS, useFeatureIsOn } from "@komi-app/flags-sdk";
import { useAnalytics } from "../../../../hooks/useAnalytics";
import { SEGMENT_EVENTS } from "../../../../constants/segment";
import { useCreatorTracking, CreatorEvent } from "@komi-app/analytics-sdk";
import { Area } from "react-easy-crop/types";
import When from "@komi-app/when";

const API_URL = config.api.url;
const { Dragger } = Upload;

const ProfilePhoto: React.FC = () => {
  const {
    handleBeforeCrop,
    handleChange,
    handleCompletedCrop,
    handleCompletedCropUpdate,
    handleRemovePicture,
    isAutoSaveSuccess,
    photoUpload,
    photoUploadSrc,
    user,
    isImageRequirementsOn,
  } = useProfilePhoto();

  return (
    <div
      id="profile-photo"
      className="profile-photo"
      data-testid="profile-photo__wrapper"
    >
      {!!photoUpload?.url && (
        <Row
          className="m__t--16 m__b--20 m__l--16"
          align="middle"
          justify="space-between"
        >
          <Col>
            <Text preset="semibold18" data-testid="profile-photo__title">
              Profile Photo
            </Text>
          </Col>
        </Row>
      )}
      <div>
        <Row>
          {photoUpload?.url && (
            <div
              className="profile-photo__wrapper m__l--20 m__r--4"
              data-testid="profile-photo__upload"
            >
              {!user ? (
                <ProfilePhotoLoading />
              ) : (
                <>
                  <ProfileImageCropUpdate
                    src={photoUpload.url ? photoUpload?.url?.toString() : ""}
                    beforeCrop={handleBeforeCrop}
                    aspect={175 / 220}
                    handleCompletedCropUpdate={handleCompletedCropUpdate}
                  >
                    <div className="profile-photo__preview-wrapper">
                      <LazyLoadImage
                        src={photoUploadSrc}
                        alt="avatar"
                        style={{ width: "100%", height: 220 }}
                        effect="blur"
                        data-testid="profile-photo__preview"
                      />
                    </div>
                  </ProfileImageCropUpdate>

                  <Button
                    onClick={handleRemovePicture}
                    className="btn-delete btn--circle x-button"
                    data-testid="profile-photo__delete"
                  >
                    <Icon name="close-black" />
                  </Button>
                </>
              )}
            </div>
          )}
          <div className="onboarding-header-photo p__l--16 p__b--16">
            {!photoUpload?.url && (
              <Row
                className="m__t--16 m__b--20"
                align="middle"
                justify="space-between"
              >
                <Col>
                  <Text preset="semibold18">Profile Photo</Text>
                </Col>
              </Row>
            )}
            <div className="profile-photo__wrapper">
              {!user ? (
                <ProfilePhotoLoading />
              ) : (
                <>
                  <ProfileImageCropUpload
                    beforeCrop={handleBeforeCrop}
                    aspect={175 / 220}
                    handleCompletedCrop={handleCompletedCrop}
                    data-testid="profile-photo__upload"
                  >
                    <Dragger
                      className="p__x--16 p__t--33 "
                      accept="image/png,image/jpeg,image/webp"
                      action={API_URL}
                      showUploadList={false}
                      onChange={({ file }) => {
                        handleChange(file, {
                          metaId: photoUpload?.id,
                        });
                      }}
                      data-testid="profile-photo__upload-dragger"
                    >
                      {(photoUpload?.percent as number) < 100 ||
                      photoUpload?.loading ? (
                        <Progress value={photoUpload?.percent} />
                      ) : (
                        <Row align="middle" justify="center">
                          <Col>
                            <Icon name="add-blue" />
                          </Col>
                          <Col>
                            <Text className="d--block" preset="semibold16">
                              Replace Profile Photo
                            </Text>
                            <When
                              value={isImageRequirementsOn}
                              then={
                                <Text preset="regular14">
                                  Use a size that’s at least 564 x 710 pixels
                                  and 6MB or less
                                </Text>
                              }
                            />
                          </Col>
                        </Row>
                      )}
                    </Dragger>
                  </ProfileImageCropUpload>
                </>
              )}
            </div>
            {user && !user?.talentProfile?.avatar && isAutoSaveSuccess && (
              <Paragraph preset="regular12" className="text--red m__t--8">
                Please upload an image
              </Paragraph>
            )}
          </div>
        </Row>
      </div>
    </div>
  );
};

export const useProfilePhoto = () => {
  const dispatch = useDispatch();
  const isTemplateSelectionOn = useFeatureIsOn(
    FLAGS.GS_146_ADD_TEMPLATE_SELECTION,
  );
  const isProfilePictureUploadErrorEventsOn = useFeatureIsOn(
    FLAGS.GS_155_PROFILE_PICTURE_UPLOAD_ERROR_EVENTS,
  );
  const isProfilePictureRequirementsOn = !useFeatureIsOn(
    FLAGS.FEAT_GS_198_REMOVE_HEADER_IMAGE_REQUIREMENTS,
  );
  const isNewEditorOn = useFeatureIsOn(FLAGS.FEAT_SB_495_HEADER_ASPECT_RATIO);
  const { sendSegmentEvent } = useAnalytics();
  const user: User | null | undefined = useTypedSelector(selectUserData);
  const isAutoSaveSuccess = useTypedSelector(selectIsAutoSaveSuccess);
  const [photoUpload, setPhotoUpload] = useState<MediaUpload>();
  const photoUploadSrc = photoUpload?.url?.toString();
  const [cropParams, setCropParams] = useState({
    width: 0,
    height: 0,
    x: 0,
    y: 0,
    cropperParams: {
      x: 0,
      y: 0,
      zoomVal: 1,
    },
  });
  const imgRef: any = useRef(null); // cache preload data img
  const useAnalyticsSDK = useFeatureIsOn(FLAGS.USE_ANALYTICS_SDK_TALENT);
  const { createTracker } = useCreatorTracking();
  const profilePictureDimensionsTooSmallError = createTracker(
    CreatorEvent.PROFILE_PICTURE_DIMENSIONS_TOO_SMALL_ERROR,
  );
  const profilePictureFileTooLargeError = createTracker(
    CreatorEvent.PROFILE_PICTURE_FILE_TOO_LARGE_ERROR,
  );

  useEffect(() => {
    if (photoUpload?.url) {
      const img = new Image();
      const imgObj = new URL(photoUpload.url.toString());
      imgRef.current = img; // reference for img, make sure it wont be clear
      img.src = `${imgObj.origin}${imgObj.pathname}`; // preload data img
    }
  }, [photoUpload?.url]);

  useEffect(() => {
    setPhotoUpload({
      id: 0,
      url: user?.talentProfile?.avatar,
      fileName: user?.talentProfile?.avatar,
    });
  }, []);

  useEffect(() => {
    if (isTemplateSelectionOn) {
      setPhotoUpload({
        id: 0,
        url: user?.talentProfile?.avatar,
        fileName: user?.talentProfile?.avatar,
      });
    }
  }, [user?.talentProfile?.avatar, isTemplateSelectionOn]);

  const updateProfilePicture = useCallback(
    (photo: MediaUpload) => {
      dispatch(
        setTalentProfileAction({
          avatar: photo.url,
        }),
      );
    },
    [dispatch],
  );

  // final step for upload new photo
  const handleChange = async (
    file: UploadFile<any>,
    id: { metaId: number | undefined },
  ) => {
    try {
      let photo: MediaUpload = {};
      if (file.status === "uploading") {
        photo.loading = true;
        photo.fileName = file.name;
        setPhotoUpload({ ...photoUpload, ...photo });
        return;
      }

      // TODO: remove status error when integrate with API
      if (file.status === "done" || file.status === "error") {
        const url = await pushImageToS3(file, (value: number) =>
          setPhotoUpload((values) => ({ ...values, percent: value })),
        );

        if (!url) {
          photo = {
            id: id.metaId,
            fileName: undefined,
            loading: false,
          };
        } else {
          const urlObj = new URL(url);

          // set crop params for imagekit api
          urlObj.searchParams.set(
            "tr",
            `w-${cropParams.width},h-${cropParams.height},cm-extract,x-${cropParams.x},y-${cropParams.y}`,
          );

          // set cropper params for next time edit photo
          urlObj.searchParams.set(
            "crp",
            JSON.stringify(cropParams.cropperParams),
          );
          photo = {
            id: id.metaId,
            fileName: file.name,
            url: urlObj.toString(),
            loading: false,
          };
        }
      }

      updateProfilePicture({ ...photoUpload, ...photo });
      setPhotoUpload({ ...photoUpload, ...photo });
    } catch (ex) {
      console.error(ex);
    }
  };

  const uploadAndUpdateProfileImage = async (
    imageFile: File,
    cropParams: Area,
  ) => {
    const imageUrl = await uploadImageToS3(imageFile);

    let photo: MediaUpload = {};
    if (!imageUrl) {
      photo = {
        id: 0,
        fileName: undefined,
        loading: false,
      };
    } else {
      const urlObj = new URL(imageUrl);

      // set crop params for imagekit api
      urlObj.searchParams.set(
        "tr",
        `w-${cropParams.width},h-${cropParams.height},cm-extract,x-${cropParams.x},y-${cropParams.y}`,
      );

      // set cropper params for next time edit photo
      urlObj.searchParams.set("crp", JSON.stringify(cropParams));
      photo = {
        fileName: imageFile.name,
        url: urlObj.toString(),
        loading: false,
      };
    }

    const mediaUpload = { ...photoUpload, ...photo };

    updateProfilePicture(mediaUpload);
    setPhotoUpload((prevState) => ({ ...prevState, ...photo }));

    return mediaUpload.url;
  };

  // Use for upload new photo, Set crop params before call handleChange
  const handleCompletedCrop = ({ cropParams }: any) => {
    setCropParams(cropParams);
  };

  const handleRemovePicture = () => {
    setPhotoUpload({});
    dispatch(
      setTalentProfileAction({
        avatar: null,
      }),
    );
  };

  const handleBeforeCrop = async (file: RcFile) => {
    const data: any = await loadImage(file);
    if (data) {
      if (
        isProfilePictureRequirementsOn &&
        (data.width < 564 || data.height < 710)
      ) {
        if (isProfilePictureUploadErrorEventsOn) {
          const { width, height } = data;

          useAnalyticsSDK
            ? profilePictureDimensionsTooSmallError({
                height,
                width,
              })
            : sendSegmentEvent(
                SEGMENT_EVENTS.PROFILE_PICTURE_DIMENSIONS_TOO_SMALL_ERROR,
                {
                  "Image width": width,
                  "Image height": height,
                },
              );
        }
        notification.error({
          message: "Your image must be larger than 564 x 710 pixels",
        });
        return false;
      }
    }

    if (!isProfilePictureRequirementsOn) {
      // skip validating image size
      return;
    }

    const beforeUploadResult = onBeforeUpload(file, true);

    if (isProfilePictureUploadErrorEventsOn && !beforeUploadResult) {
      const { size } = file;
      useAnalyticsSDK
        ? profilePictureFileTooLargeError({ size })
        : sendSegmentEvent(
            SEGMENT_EVENTS.PROFILE_PICTURE_FILE_TOO_LARGE_ERROR,
            {
              "Uploaded file size": size,
            },
          );
    }

    return beforeUploadResult;
  };

  // Final step when edit profile photo
  const handleCompletedCropUpdate = ({ cropParams }: any) => {
    setCropParams(cropParams);

    // Set photo url
    if (photoUpload?.url) {
      const urlObj = new URL(photoUpload?.url.toString());
      urlObj.search = "";

      // Set crop params for imagekit api
      urlObj.searchParams.set(
        "tr",
        `w-${cropParams.width},h-${cropParams.height},cm-extract,x-${cropParams.x},y-${cropParams.y}`,
      );

      // set cropper params for next time edit photo
      urlObj.searchParams.set("crp", JSON.stringify(cropParams.cropperParams));

      const url = urlObj.toString();
      updateProfilePicture({ ...photoUpload, url });
      setPhotoUpload({ ...photoUpload, url });
    }
  };

  return {
    isNewEditorOn,
    isAutoSaveSuccess,
    photoUpload,
    photoUploadSrc,
    user,
    handleBeforeCrop,
    handleChange,
    handleCompletedCrop,
    handleCompletedCropUpdate,
    handleRemovePicture,
    uploadAndUpdateProfileImage,
    isImageRequirementsOn: isProfilePictureRequirementsOn,
  };
};

export default ProfilePhoto;
