import { useEffect, useMemo, useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
import { useDispatch } from "react-redux";
import unionBy from "lodash/unionBy";

import When from "@komi-app/when";

import { useTypedSelector } from "../../redux/rootReducer";
import {
  selectLocalizationSelected,
  selectTalentProfile,
  selectTalentProfileModules,
} from "../../redux/User/selector";
import { setTalentProfileAction } from "../../redux/User/actions";
import {
  SocialProfileLink,
  SocialProfileLinkTypes,
} from "../../redux/User/types";
import { useAutoSave } from "../../hooks/useAutoSave";

import { Area } from "react-easy-crop/types";
import { useProfilePhoto } from "../Profile/Header/ProfilePhoto/ProfilePhoto";

import useMobileView from "../../hooks/useMobileView";
import { useWindowSize } from "../../hooks";
import { AuthApiSauce } from "../../services";
import { SEGMENT_EVENTS } from "../../constants/segment";
import { Response } from "../../redux/Common/types";
import { useAnalytics } from "../../hooks/useAnalytics";

import { FLAGS, useFeatureIsOn } from "@komi-app/flags-sdk";
import { CreatorEvent, useCreatorTracking } from "@komi-app/analytics-sdk";
import "./onboardingFlow.scss";

import {
  CompleteProfileReviewPage,
  HeaderImageCropPage,
  HeaderImageUploadPage,
  SocialLink,
  SocialLinksPage,
  SocialLinkType,
} from "@komi-app/creator-ui";
import { useTalentProfileCategory } from "../../hooks/useTalentProfileCategory";
import { useHeaderImage } from "hooks/user-hooks/useHeaderImage";

function useTalentProfileDisplayName() {
  const talentProfile = useTypedSelector(selectTalentProfile);
  const { displayName } = talentProfile || {};
  return displayName;
}

function useSocialLinks() {
  const talentProfile = useTypedSelector(selectTalentProfile);
  const { socialProfileLinks } = talentProfile || {};
  return socialProfileLinks;
}

function isResponseSuccess(response: Response<unknown> | null): boolean {
  if (response && "ok" in response) {
    return !!response.ok;
  }

  // GeneralApiProblem do not contain the `ok` property
  return false;
}

function useUpdateSocialLinks() {
  const dispatch = useDispatch();
  const existingLinks = useSocialLinks();
  return (links: SocialProfileLink[]) => {
    const newLinksWithValues = links.filter((link) => !!link.link);
    const socialProfileLinks = unionBy(
      newLinksWithValues,
      existingLinks,
      "type"
    );
    dispatch(
      setTalentProfileAction({
        socialProfileLinks: socialProfileLinks,
      })
    );

    return socialProfileLinks;
  };
}

function useCurrentPage() {
  const location = useLocation();
  const { pathname } = location;

  return pathname.replaceAll("/admin/onboarding/", "");
}

export default function OnboardingFlow() {
  const { sendSegmentEvent } = useAnalytics();
  const category = useTalentProfileCategory();
  const displayName = useTalentProfileDisplayName();

  const existingLinks = useSocialLinks();
  const existingLinksToPrePopulate = useMemo(() => {
    if (!existingLinks) {
      return [];
    }
    return existingLinks
      .filter((link: SocialProfileLink) =>
        Object.keys(SocialLinkType).includes(link.type)
      )
      .map((link) => {
        return {
          type: link.type as unknown as SocialLinkType,
          link: link.link,
        };
      });
  }, [existingLinks]);

  const history = useHistory();
  const headerImageSrc = useHeaderImage();

  const mobileView = useMobileView();
  const { width } = useWindowSize();
  const isNotSupported = mobileView ? false : !!(width && width < 1040);

  const localizationSelected = useTypedSelector(selectLocalizationSelected);
  const talentProfile = useTypedSelector(selectTalentProfile);
  const modules = useTypedSelector(selectTalentProfileModules);

  const { uploadAndUpdateProfileImage } = useProfilePhoto();

  const { onSaveProfile } = useAutoSave();
  const updateSocialLinks = useUpdateSocialLinks();

  const currentPage = useCurrentPage();

  const [socialIcons, setSocialIcons] = useState<SocialLinkType[]>(() => {
    if (!existingLinks) {
      return [];
    }

    return existingLinks
      .filter((link: SocialProfileLink) =>
        Object.keys(SocialLinkType).includes(link.type)
      )
      .map((link: SocialProfileLink) => link.type as unknown as SocialLinkType);
  });
  const [headerImage, setHeaderImage] = useState<File | undefined>(undefined);

  const [loading, setLoading] = useState<boolean>(false);
  const [showEmailSent, setShowEmailSent] = useState(false);

  const isSocialLinksPageSkippable = !useFeatureIsOn(
    FLAGS.GS_196_ONBOARDING_SOCIAL_LINKS_SCREEN_DISABLE_SKIP
  );
  const isHeaderImageUploadPageSkippable = !useFeatureIsOn(
    FLAGS.GS_196_ONBOARDING_HEADER_IMAGE_UPLOAD_SCREEN_DISABLE_SKIP
  );
  const isSocialLinksInputsAutoCompleteAutoCorrectOff = useFeatureIsOn(
    FLAGS.FEAT_SB_328_ONBOARDING_USERNAME_DISABLE_AUTOCOMPLETE_AUTOCAPITALISE
  );
  const enableHandles = useFeatureIsOn(
    FLAGS.FEAT_SB_319_ONBOARDING_ACCEPT_SOCIAL_HANDLES
  );

  const useAnalyticsSDK = useFeatureIsOn(FLAGS.USE_ANALYTICS_SDK_TALENT);
  const { createTracker } = useCreatorTracking();

  const completeOnboardingCompleteProfileScreen = createTracker(
    CreatorEvent.COMPLETE_ONBOARDING_COMPLETE_PROFILE_SCREEN
  );
  const completeOnboardingHeaderImageCropScreen = createTracker(
    CreatorEvent.COMPLETE_ONBOARDING_HEADER_IMAGE_CROP_SCREEN
  );
  const completeOnboardingHeaderImageUploadSceen = createTracker(
    CreatorEvent.COMPLETE_ONBOARDING_HEADER_IMAGE_UPLOAD_SCREEN
  );
  const completeOnboardingSocialLinksScreen = createTracker(
    CreatorEvent.COMPLETE_ONBOARDING_SOCIAL_LINKS_SCREEN
  );
  const requestLoginEmailFailure = createTracker(
    CreatorEvent.REQUEST_LOGIN_EMAIL_FAILURE
  );
  const requestLoginEmailSuccess = createTracker(
    CreatorEvent.REQUEST_LOGIN_EMAIL_SUCCESS
  );

  function handlePageSkip() {
    const industry = category?.name;
    const status = "skipped";

    if (currentPage === "social-links") {
      useAnalyticsSDK
        ? completeOnboardingSocialLinksScreen({
            industry,
            status,
          })
        : sendSegmentEvent(
            SEGMENT_EVENTS.COMPLETE_ONBOARDING_SOCIAL_LINKS_SCREEN,
            {
              Industry: industry,
              Status: status,
            }
          );
      history.push("/admin/onboarding/header-image");
    } else if (currentPage === "header-image" && !headerImage) {
      useAnalyticsSDK
        ? completeOnboardingHeaderImageUploadSceen({
            industry,
            status,
          })
        : sendSegmentEvent(
            SEGMENT_EVENTS.COMPLETE_ONBOARDING_HEADER_IMAGE_UPLOAD_SCREEN,
            {
              Industry: industry,
              Status: status,
            }
          );
      history.push("/admin/onboarding/complete");
    }
  }

  function handleSocialLinkUpdate(links: SocialLink[]) {
    setLoading(true);

    const socialLinksToSave = links.map((link) => {
      return {
        type: link.type as unknown as SocialProfileLinkTypes,
        link: link.link,
      };
    });
    const updatedLinks = updateSocialLinks(socialLinksToSave);

    setSocialIcons(
      links.filter((link) => !!link.link).map((link) => link.type)
    );
    onSaveProfile({
      newTalent: {
        ...talentProfile,
        socialProfileLinks: updatedLinks,
      },
      newModules: modules,
      localizationId: localizationSelected?.id,
      callback: () => {
        setLoading(false);
        const industry = category?.name;
        const status = "success";

        useAnalyticsSDK
          ? completeOnboardingSocialLinksScreen({
              industry,
              status,
            })
          : sendSegmentEvent(
              SEGMENT_EVENTS.COMPLETE_ONBOARDING_SOCIAL_LINKS_SCREEN,
              {
                Industry: industry,
                Status: status,
              }
            );
        history.push("/admin/onboarding/header-image");
      },
      errorCallback: () => {
        setLoading(false);
      },
    });
  }

  function handleImageSelect(file: File) {
    const industry = category?.name;
    const status = "success";

    useAnalyticsSDK
      ? completeOnboardingHeaderImageUploadSceen({
          industry,
          status,
        })
      : sendSegmentEvent(
          SEGMENT_EVENTS.COMPLETE_ONBOARDING_HEADER_IMAGE_UPLOAD_SCREEN,
          {
            Industry: industry,
            Status: status,
          }
        );
    setHeaderImage(file);
  }

  const sendLoginLinkEmail = async () => {
    const response = await AuthApiSauce.sendLoginLinkEmail();

    const isSuccess = isResponseSuccess(response);
    if (isSuccess) {
      useAnalyticsSDK
        ? requestLoginEmailSuccess()
        : sendSegmentEvent(SEGMENT_EVENTS.REQUEST_LOGIN_EMAIL_SUCCESS);
    } else {
      useAnalyticsSDK
        ? requestLoginEmailFailure()
        : sendSegmentEvent(SEGMENT_EVENTS.REQUEST_LOGIN_EMAIL_FAILURE);
    }

    return isSuccess;
  };

  async function handleOnboardingComplete() {
    const industry = category?.name;
    const status = "success";

    if (isNotSupported) {
      setLoading(true);
      try {
        const isSuccess = await sendLoginLinkEmail();
        if (isSuccess) {
          useAnalyticsSDK
            ? completeOnboardingCompleteProfileScreen({ status, industry })
            : sendSegmentEvent(
                SEGMENT_EVENTS.COMPLETE_ONBOARDING_COMPLETE_PROFILE_SCREEN,
                {
                  Industry: industry,
                  Status: status,
                }
              );
          setShowEmailSent(true);
        }
      } finally {
        setLoading(false);
      }
    } else {
      useAnalyticsSDK
        ? completeOnboardingCompleteProfileScreen({ status, industry })
        : sendSegmentEvent(
            SEGMENT_EVENTS.COMPLETE_ONBOARDING_COMPLETE_PROFILE_SCREEN,
            {
              Industry: industry,
              Status: status,
            }
          );
      window.open("/admin", "_self");
    }
  }

  async function handleCropComplete(
    croppedArea: Area,
    croppedAreaPixels: Area
  ) {
    if (!headerImage) {
      return;
    }
    setLoading(true);

    try {
      const avatarUrl = await uploadAndUpdateProfileImage(
        headerImage!,
        croppedAreaPixels
      );

      onSaveProfile({
        newTalent: { ...talentProfile, avatar: avatarUrl },
        newModules: modules,
        localizationId: localizationSelected?.id,
        callback: () => {
          setLoading(false);
          const industry = category?.name;
          const status = "success";

          useAnalyticsSDK
            ? completeOnboardingHeaderImageCropScreen({ status, industry })
            : sendSegmentEvent(
                SEGMENT_EVENTS.COMPLETE_ONBOARDING_HEADER_IMAGE_CROP_SCREEN,
                {
                  Industry: industry,
                  Status: status,
                }
              );
          history.push("/admin/onboarding/complete");
        },
        errorCallback: () => {
          setLoading(false);
        },
      });
    } catch (e) {
      setLoading(false);
    }
  }

  useEffect(() => {
    const industry = category?.name;
    if (currentPage === "social-links") {
      useAnalyticsSDK
        ? completeOnboardingSocialLinksScreen({ industry })
        : sendSegmentEvent(SEGMENT_EVENTS.VIEW_ONBOARDING_SOCIAL_LINKS_SCREEN, {
            Industry: category?.name,
          });
    } else if (currentPage === "header-image" && !headerImage) {
      useAnalyticsSDK
        ? completeOnboardingHeaderImageUploadSceen({ industry })
        : sendSegmentEvent(
            SEGMENT_EVENTS.VIEW_ONBOARDING_HEADER_IMAGE_UPLOAD_SCREEN,
            {
              Industry: category?.name,
            }
          );
    } else if (currentPage === "header-image" && headerImage) {
      useAnalyticsSDK
        ? completeOnboardingHeaderImageCropScreen({ industry })
        : sendSegmentEvent(
            SEGMENT_EVENTS.VIEW_ONBOARDING_HEADER_IMAGE_CROP_SCREEN,
            {
              Industry: category?.name,
            }
          );
    } else if (currentPage === "complete") {
      useAnalyticsSDK
        ? completeOnboardingCompleteProfileScreen({ industry })
        : sendSegmentEvent(
            SEGMENT_EVENTS.VIEW_ONBOARDING_COMPLETE_PROFILE_SCREEN,
            {
              Industry: category?.name,
            }
          );
    }
  }, [currentPage]);

  return (
    <>
      <When
        value={currentPage === "social-links"}
        then={
          <SocialLinksPage
            category={category?.name}
            displayName={displayName}
            onSubmit={handleSocialLinkUpdate}
            existingLinks={existingLinksToPrePopulate}
            isSkippable={isSocialLinksPageSkippable}
            onSkip={handlePageSkip}
            loading={loading}
            autoCompleteAutoCorrectOff={
              isSocialLinksInputsAutoCompleteAutoCorrectOff
            }
            useHandles={enableHandles}
          />
        }
      />

      <When
        value={currentPage === "header-image" && !headerImage}
        then={
          <HeaderImageUploadPage
            displayName={displayName}
            onImageSelect={handleImageSelect}
            previewIcons={socialIcons}
            isSkippable={isHeaderImageUploadPageSkippable}
            onSkip={handlePageSkip}
          />
        }
      />

      <When
        value={currentPage === "header-image" && headerImage}
        then={
          <HeaderImageCropPage
            displayName={displayName}
            previewIcons={socialIcons}
            imageFile={headerImage!}
            onImageChange={handleImageSelect}
            onCropComplete={handleCropComplete}
            loading={loading}
          />
        }
      />

      <When
        value={currentPage === "complete"}
        then={
          <CompleteProfileReviewPage
            displayName={displayName}
            previewIcons={socialIcons}
            headerImageSrc={headerImageSrc}
            isNotSupported={isNotSupported}
            onButtonClick={handleOnboardingComplete}
            loading={loading}
            showEmailSent={showEmailSent}
          />
        }
      />
    </>
  );
}
