import { Button } from "antd";
import PopupWindow from "components/PopupWindowSpotifyAuth";
import copyToClipboard from "copy-to-clipboard";

import { FLAGS, useFeatureIsOn } from "@komi-app/flags-sdk";
import classNames from "classnames";
import DragDropContext from "components/DragDropContext";
import PodcastCardModule from "components/PodcastCardModule";
import PodcastLatestSyncItem from "components/PodcastLatestSyncItem";
import PodcastModal from "components/PodcastModal";
import PortalComponent from "components/PortalComponent/PortalComponent";
import config from "config";
import { PODCAST_MODAL_STEP } from "constants/module";
import { SEGMENT_EVENTS } from "constants/segment";
import { useAnalytics } from "hooks/useAnalytics";
import { useModules } from "hooks/useModules";
import Cookies from "js-cookie";
import reduce from "lodash/reduce";
import {
  PodcastItem,
  TalentProfileModule,
} from "models/talent/talent-profile-module.model";
import React, { useCallback, useMemo, useState } from "react";
import { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
import {
  selectLocalizationSelected,
  selectUserData,
} from "redux/User/selector";
import { SpotifyUser } from "redux/User/types";
import { useTypedSelector } from "redux/rootReducer";
import { spotifyService, userService } from "services";
import {
  KOMI_SPOTIFY_ACCESS_TOKEN,
  KOMI_SPOTIFY_REFRESH_TOKEN,
} from "services/SpotifyService";
import { ArrayServices } from "utils/array";
import notification from "utils/notification";
import { convertToUrl } from "utils/url";
import { Icon } from "../../../components/Icon";
import { Paragraph } from "../../../components/Typography";
import { useWindowSize } from "../../../hooks";
import ModuleEditor from "../ModuleEditor";
import EmptyModule from "./EmptyModule";
import { ModuleType } from "@komi-app/shared-types";
import { useCreatorTracking, CreatorEvent } from "@komi-app/analytics-sdk";
import { trackingProps } from "utils/tracking";

const MusicCardMemo = React.memo(PodcastCardModule);

interface ModuleSmartPodcastProps {
  module: TalentProfileModule<PodcastItem>;
  dragHandleProps?: DraggableProvidedDragHandleProps;
  active: boolean;
}

const ModuleSmartPodcast: React.FC<ModuleSmartPodcastProps> = ({
  module,
  dragHandleProps,
  active,
}) => {
  const { sendSegmentEvent } = useAnalytics();
  const profileContext = useModules();
  const localizationSelected = useTypedSelector(selectLocalizationSelected);
  const user = useTypedSelector(selectUserData);
  const [modalStatus, setModalStatus] = useState<{
    visible: boolean;
    status: PODCAST_MODAL_STEP;
    item?: PodcastItem;
  }>({
    visible: false,
    status: PODCAST_MODAL_STEP.SELECT_PODCAST_TYPE,
    item: undefined,
  });
  const item = useMemo(() => {
    return module.items[0];
  }, [module.items]);
  const itemList = useMemo(() => module.items, [module.items]);

  const { loadingShop, thirdPartyData } = profileContext;
  const loading = useMemo(() => {
    return loadingShop.some((key: string) => key === module.id);
  }, [loadingShop, module.id]);
  const data = useMemo(() => {
    return thirdPartyData?.find((item: any) => item.id === module.id);
  }, [thirdPartyData, module.id]);
  const collection = useMemo(() => data?.collection, [data]);

  const hasSpotifyPopupFix = useFeatureIsOn(FLAGS.FIX_SB_286_SPOTIFY_POPUP);
  const useAnalyticsSDK = useFeatureIsOn(FLAGS.USE_ANALYTICS_SDK_TALENT);
  const { createTracker } = useCreatorTracking()
  const elementCreate = createTracker(CreatorEvent.ELEMENT_CREATED);

  const onEditModuleCallback = useCallback(
    (moduleEdit: TalentProfileModule<PodcastItem>) => {
      profileContext.setModule(moduleEdit);
    },
    [profileContext.setModule]
  );

  const onEditSyncLatestPodcast = useCallback(() => {
    setModalStatus({
      visible: true,
      item: undefined,
      status: PODCAST_MODAL_STEP.SELECT_PODCAST_TYPE,
    });
    setTimeout(() => {
      setModalStatus((values) => ({
        ...values,
        item,
        status: PODCAST_MODAL_STEP.SYNC_LATEST,
      }));
    }, 50);
  }, [item]);

  const onSaveCallback = useCallback(
    (data: any) => {
      let moduleEdit;
      if (modalStatus.item) {
        moduleEdit = {
          ...module,
          items: ArrayServices.updateWithIndex(
            module.items,
            modalStatus.item.order as number,
            { ...modalStatus.item, ...data }
          ),
          isUpdate: true,
        };
      } else {
        moduleEdit = {
          ...module,
          items: [{ ...data, order: 0 }, ...module.items].map(
            (el, index: number) => ({ ...el, order: index })
          ),
          isUpdate: true,
          type:
            modalStatus.status === PODCAST_MODAL_STEP.SYNC_LATEST
              ? ModuleType.PODCAST_AUTOMATION
              : ModuleType.PODCAST,
        };
        
        profileContext.setModule(moduleEdit);

        const {
          pageId,
          pageName,
          type
        } = trackingProps(
            modalStatus.status === PODCAST_MODAL_STEP.SYNC_LATEST
            ? ModuleType.PODCAST_AUTOMATION
            : ModuleType.PODCAST,
          localizationSelected)

        useAnalyticsSDK
          ? elementCreate({ pageId, pageName, type })
          : sendSegmentEvent(SEGMENT_EVENTS.ELEMENT_CREATED, {
            "Module Type": type,
            "Page ID": localizationSelected?.id || null,
            "Page Name": localizationSelected?.name || "Default",
          });
      }
      profileContext.setModule(moduleEdit);
    },
    [module, localizationSelected, profileContext.setModule, modalStatus]
  );

  const onDropEndPodcasts = useCallback(
    (list: PodcastItem[]) => {
      onEditModuleCallback({
        ...module,
        items: list.map((item, index) => ({ ...item, order: index })),
        isUpdate: true,
      });
    },
    [module, onEditModuleCallback]
  );

  const onAddPodcastModule = useCallback(
    (isIndividual: boolean) => () => {
      setModalStatus({
        visible: true,
        status: PODCAST_MODAL_STEP.SELECT_PODCAST_TYPE,
        item: undefined,
      });
      if (isIndividual) {
        setTimeout(() => {
          setModalStatus({
            visible: true,
            status: PODCAST_MODAL_STEP.INDIVIDUAL,
            item: undefined,
          });
        }, 100);
      }
    },
    []
  );

  const onEditIndividual = useCallback((podcast: PodcastItem) => {
    setModalStatus({
      visible: true,
      status: PODCAST_MODAL_STEP.SELECT_PODCAST_TYPE,
      item: undefined,
    });
    setTimeout(() => {
      setModalStatus({
        visible: true,
        status: PODCAST_MODAL_STEP.INDIVIDUAL,
        item: podcast,
      });
    }, 100);
  }, []);

  const onDeletePodcast = useCallback(
    (podcast: PodcastItem) => {
      const items = reduce(
        module.items,
        (results: any, item: any) => {
          if (item.order !== podcast.order) {
            return [...results, { ...item, order: results.length }];
          }
          return results;
        },
        []
      );

      profileContext.setModule({
        ...module,
        items,
        isUpdate: true,
        type: !items.length
          ? ModuleType.PODCAST_SELECT
          : module.type,
      });
    },
    [module, profileContext.setModule]
  );

  const handleRefreshToken = async () => {
    try {
      const result = await userService.spotifyRefreshToken();

      if (result && "ok" in result) {
        spotifyService.signin(result.response);
        return true;
      } else {
        throw new Error("Cann't refresh token spotify.");
      }
    } catch (ex: any) {
      const signIn = await handleSpotifySignIn();
      return signIn;
    }
  };

  const handleSpotifySignIn = async () => {
    return new Promise(async (resolve) => {
      if (hasSpotifyPopupFix) {
        const popup = PopupWindow.open("spotify-authorization", "about:blank", {
          height: 1000,
          width: 600,
        });

        const result = await userService.spotifyConnect({
          callbackUrl: window.location.href,
        });
        if (!!result && "ok" in result) {
          popup.navigate(result.response.url);

          popup.then(
            (data: SpotifyUser) => {
              spotifyService.signin(data);
              resolve(true);
            },
            (error: any) => {
              resolve(false);
              console.error(error);
            }
          );
        }
      } else {
        const result = await userService.spotifyConnect({
          callbackUrl: window.location.href,
        });
        if (!!result && "ok" in result) {
          const popup = PopupWindow.open(
            "spotify-authorization",
            result.response.url,
            {
              height: 1000,
              width: 600,
            }
          );

          popup.then(
            (data: SpotifyUser) => {
              spotifyService.signin(data);
              resolve(true);
            },
            (error: any) => {
              resolve(false);
              console.error(error);
            }
          );
        }
      }
    });
  };

  const handleConnectSpotify = async () => {
    const token = Cookies.get(KOMI_SPOTIFY_ACCESS_TOKEN);
    if (token) {
      return true;
    }
    if (
      user?.spotifyRefreshToken ||
      user?.thirdPartyInfo?.spotifyRefreshToken ||
      Cookies.get(KOMI_SPOTIFY_REFRESH_TOKEN)
    ) {
      const result = await handleRefreshToken();
      return result;
    } else {
      const result = await handleSpotifySignIn();
      return result;
    }
  };

  const onBeforeEditProduct = useCallback(async (podcast: PodcastItem) => {
    onEditIndividual(podcast);
  }, []);
  const onCopySmartLink = useCallback(
    (podcast: PodcastItem) => {
      const komiLink =
        config.service.env === "development"
          ? `${user?.username}-dev.komi.io`
          : config.service.env === "staging"
          ? `${user?.username}-staging.komi.io`
          : `${user?.username}.komi.io`;
      const link = `${komiLink}/podcast/${
        podcast.customUrl
          ? podcast.customUrl
          : convertToUrl(podcast.metadata?.name)
      }`;
      copyToClipboard(link);
      notification.success({
        message:
          "The smart link has been copied to clipboard. Your updates need to be published before the link can be accessed.",
      });
    },
    [user]
  );

  const renderContent = () => {
    if (!module.items.length) {
      return (
        <React.Fragment>
          <EmptyModule
            titleAction="Add New Podcast"
            onClick={onAddPodcastModule(false)}
          />
        </React.Fragment>
      );
    }

    if (module.type === ModuleType.PODCAST_AUTOMATION) {
      return (
        <PodcastLatestSyncItem
          moduleId={module.id}
          loading={loading}
          collection={collection}
          item={item}
          onDelete={onDeletePodcast}
          active={active}
          onEdit={onEditSyncLatestPodcast}
          module={module}
        />
      );
    }

    const { width } = useWindowSize();

    const isMobileStyleChangesEnabled = width && width <= 768;

    return (
      <React.Fragment>
        <div
          className={classNames(
            "d--flex justify__content--between align__items--center",
            {
              "m__b--8": isMobileStyleChangesEnabled,
              "m__b--22": !isMobileStyleChangesEnabled,
            }
          )}
        >
          <Button
            className="add-item-btn p--0"
            type="link"
            onClick={onAddPodcastModule(true)}
          >
            <div className="d--flex justify__content--center align__items--center">
              <Icon name="add-blue" />
              <Paragraph preset="semibold18" className="text--blue m__l--4">
                Add New Podcast
              </Paragraph>
            </div>
          </Button>
          <Paragraph preset="medium14" className="text--default opacity-6">
            {itemList.length}&nbsp;
            {itemList.length > 1 ? "podcasts added" : "podcast added"}
          </Paragraph>
        </div>

        <DragDropContext
          droppableId="product-child-drop"
          listClassName="product-list"
          itemIdPrefix="product"
          direction="vertical"
          list={itemList}
          onDropEndCallback={onDropEndPodcasts}
        >
          {(dragProvided, snapshot, item, productIndex) => {
            const isRender = active ? active : productIndex < 2;
            return isRender ? (
              <PortalComponent
                innerRef={dragProvided.innerRef}
                key={productIndex}
                namespaceClass="product-list"
                provided={dragProvided}
                snapshot={snapshot}
                single={itemList?.length === 1}
              >
                <MusicCardMemo
                  titleShortcut
                  disableDragDrop={module.items.length <= 1}
                  index={productIndex}
                  disableDrag={itemList?.length === 1}
                  item={item}
                  onEdit={onBeforeEditProduct}
                  onDelete={onDeletePodcast}
                  onCopySmartLink={onCopySmartLink}
                  dragHandleProps={dragProvided.dragHandleProps}
                  deleteTitle="Are you sure you want to delete this podcast?"
                  deleteSubTitle="This podcast will be deleted and you can’t undo this action."
                  module={module}
                />
              </PortalComponent>
            ) : (
              <></>
            );
          }}
        </DragDropContext>
        {!active && itemList.length > 2 && (
          <div className="d--flex justify__content--end align__items--center m__t--20 cursor-pointer">
            <Paragraph preset="medium14" className="opacity-6">
              +{itemList.length - 2} More
            </Paragraph>
          </div>
        )}
      </React.Fragment>
    );
  };

  return (
    <React.Fragment>
      <ModuleEditor module={module} dragHandleProps={dragHandleProps}>
        <PodcastModal
          modalStatus={modalStatus}
          show={modalStatus.visible}
          setStatusModal={setModalStatus}
          step={modalStatus.status}
          onSubmit={onSaveCallback}
          item={modalStatus.item}
          cancellable={module.type !== ModuleType.PODCAST_SELECT}
          onConnectSpotify={handleConnectSpotify}
        />
        {renderContent()}
      </ModuleEditor>
    </React.Fragment>
  );
};

export default React.memo(ModuleSmartPodcast);
