import { FLAGS, useFeatureIsOn } from '@komi-app/flags-sdk'
import { Button } from 'antd'
import classNames from 'classnames'
import AddProfileSmartPodcast from 'components/AddProfileSmartPodcast'
import DragDropContext from 'components/DragDropContext'
import { Icon } from 'components/Icon'
import PodcastCardModule from 'components/PodcastCardModule'
import PopupWindow from 'components/PopupWindowSpotifyAuth'
import PortalComponent from 'components/PortalComponent/PortalComponent'
import { Text } from 'components/Typography'
import { SEGMENT_EVENTS } from 'constants/segment'
import copyToClipboard from 'copy-to-clipboard'
import { useAnalytics } from 'hooks/useAnalytics'
import { useModules } from 'hooks/useModules'
import Cookies from 'js-cookie'
import {
  PodcastItem,
  TalentProfileModule
} from 'models/talent/talent-profile-module.model'
import React, { useCallback, useEffect, useState } from 'react'
import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'
import { useDispatch } from 'react-redux'
import { updateSpotifyUserActions } from 'redux/User/actions'
import { selectLocalizationSelected, selectUserData } from 'redux/User/selector'
import { SpotifyUser } from 'redux/User/types'
import { useTypedSelector } from 'redux/rootReducer'
import { userService } from 'services'
import { createKomiDomain } from 'services/DomainService'
import {
  KOMI_SPOTIFY_ACCESS_TOKEN,
  KOMI_SPOTIFY_REFRESH_TOKEN
} from 'services/SpotifyService'
import { ArrayServices } from 'utils/array'
import { isEmptyModule } from 'utils/modules'
import { useWindowSize } from '../../../hooks'
import notification from '../../../utils/notification'
import { convertToUrl } from '../../../utils/url'
import ModuleEditor from '../ModuleEditor'
import EmptyModule from './EmptyModule'
import { useCreatorTracking, CreatorEvent } from '@komi-app/analytics-sdk'
import { trackingProps } from 'utils/tracking'
import { useAnalyticsStartItemCreation } from 'hooks/useAnalyticsStartItemCreation'
import { useAnalyticsCompleteItemCreation } from 'hooks/useAnalyticsCompleteItemCreation'

const MusicCardMemo = React.memo(PodcastCardModule)

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

const ModulePodcast: React.FC<ModulePodcastProps> = ({
  module,
  dragHandleProps,
  active
}) => {
  const { sendSegmentEvent } = useAnalytics()
  const useAnalyticsSDK = useFeatureIsOn(FLAGS.USE_ANALYTICS_SDK_TALENT)
  const { createTracker } = useCreatorTracking()
  const elementCreate = createTracker(CreatorEvent.ELEMENT_CREATED)
  const dispatch = useDispatch()
  const [musicList, setMusicList] = useState<PodcastItem[]>([])
  const [musicEditState, setMusicEditState] = useState<{
    isEdit: boolean
    music?: PodcastItem
    musicEditIndex?: number
  }>({
    isEdit: false
  })
  const localizationSelected = useTypedSelector(selectLocalizationSelected)

  const profileContext = useModules()
  const user = useTypedSelector(selectUserData)

  const [visible, setVisible] = useState(false)

  const hasSpotifyPopupFix = useFeatureIsOn(FLAGS.FIX_SB_286_SPOTIFY_POPUP)
  const { trackStartAddingItemToModule } = useAnalyticsStartItemCreation()
  const { trackCompleteAddingItemToModule } = useAnalyticsCompleteItemCreation()

  useEffect(() => {
    setMusicList(
      module.items.map((music, index) => ({
        ...music,
        order: index
      }))
    )
    return () => {}
  }, [module.items, module.visible])

  const handleRefreshToken = async (callback: any) => {
    try {
      const result = await userService.spotifyRefreshToken()
      if (result && 'ok' in result) {
        dispatch(
          updateSpotifyUserActions.REQUEST({
            ...result.response,
            callback: callback
          })
        )
      } else {
        throw new Error("Cann't refresh token spotify.")
      }
    } catch (ex: any) {
      await handleSpotifySignIn(callback)
      return
    }
  }

  const handleSpotifySignIn = async (callback: any) => {
    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) => {
            dispatch(
              updateSpotifyUserActions.REQUEST({
                ...data,
                callback: callback
              })
            )
          },
          (error: any) => {
            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) => {
            dispatch(
              updateSpotifyUserActions.REQUEST({
                ...data,
                callback: callback
              })
            )
          },
          (error: any) => {
            console.error(error)
          }
        )
      }
    }
  }

  const handleConnectSpotify = async (callback: any) => {
    if (
      user?.spotifyRefreshToken ||
      user?.thirdPartyInfo?.spotifyRefreshToken ||
      Cookies.get(KOMI_SPOTIFY_REFRESH_TOKEN)
    ) {
      await handleRefreshToken(callback)
    } else {
      await handleSpotifySignIn(callback)
    }
  }

  const onBeforeAddProduct = useCallback(async () => {
    if (!Cookies.get(KOMI_SPOTIFY_ACCESS_TOKEN)) {
      await handleConnectSpotify(() => onAddMusic())
      return
    }
    onAddMusic()
  }, [])

  const onBeforeEditProduct = useCallback(async (music: PodcastItem) => {
    if (!Cookies.get(KOMI_SPOTIFY_ACCESS_TOKEN)) {
      await handleConnectSpotify(() => onEditMusic(music))
      return
    }
    onEditMusic(music)
  }, [])

  const onAddMusic = useCallback(() => {
    trackStartAddingItemToModule(module)
    setMusicEditState(preState => ({
      ...preState,
      isEdit: false,
      music: undefined,
      musicIndex: undefined
    }))
    setVisible(true)
  }, [])

  const onEditMusic = useCallback((music: PodcastItem) => {
    setMusicEditState(preState => ({
      ...preState,
      isEdit: true,
      music: music,
      musicIndex: music.order
    }))
    setVisible(true)
  }, [])

  const onDeleteMusic = useCallback(
    (music: PodcastItem) => {
      profileContext.setModule({
        ...module,
        items: ArrayServices.removeWithIndex(
          module.items,
          music.order as number
        ),
        isUpdate: true
      })
    },
    [module, profileContext.setModule]
  )

  const onDropEndMusics = useCallback(
    (list: PodcastItem[]) => {
      profileContext.setModule({
        ...module,
        items: list.map((item, index) => ({ ...item, order: index })),
        isUpdate: true
      })
    },
    [module, profileContext.setModule]
  )

  const onSaveProductCallback = useCallback(
    (music: PodcastItem) => {
      let moduleEdit
      if (musicEditState.isEdit) {
        moduleEdit = {
          ...module,
          items: ArrayServices.updateWithIndex(
            module.items,
            music.order as number,
            music
          ),
          isUpdate: true
        }
      } else {
        moduleEdit = {
          ...module,
          items: ArrayServices.unshift(module.items, music),
          isUpdate: true
        }
      }
      profileContext.setModule(moduleEdit)
      trackCompleteAddingItemToModule(moduleEdit)
      const { pageId, pageName, type } = trackingProps(
        moduleEdit.type,
        localizationSelected
      )

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

  const handleSetVisible = (value: boolean) => {
    setVisible(value)
    setMusicEditState(preState => ({
      ...preState,
      isEdit: false,
      music: undefined,
      musicIndex: undefined
    }))
  }

  const onCopySmartLink = useCallback(
    (music: PodcastItem) => {
      const komiLink = createKomiDomain(user?.username || '')
      const link = `${komiLink}/podcast/${convertToUrl(
        music.metadata?.name
      )}?id=${music.id}`
      copyToClipboard(link)
      notification.success({
        message: 'The smart link has been copied to clipboard'
      })
    },
    [user]
  )

  const { width } = useWindowSize()

  const isMobileStyleChangesEnabled = width && width <= 768

  return (
    <React.Fragment>
      <ModuleEditor module={module} dragHandleProps={dragHandleProps}>
        {isEmptyModule(module) ? (
          <React.Fragment>
            <EmptyModule
              titleAction="Add New Podcast"
              onClick={onBeforeAddProduct}
            />
          </React.Fragment>
        ) : (
          <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={onBeforeAddProduct}
              >
                <div className="d--flex justify__content--center align__items--center">
                  <Icon name="add-blue" />
                  <Text preset="semibold18" className="text--blue m__l--4">
                    Add New Podcast
                  </Text>
                </div>
              </Button>
              <Text preset="medium14" className="text--default opacity-6">
                {musicList.length}&nbsp;
                {musicList.length > 1 ? 'podcasts added' : 'podcast added'}
              </Text>
            </div>

            <DragDropContext
              droppableId="product-child-drop"
              listClassName="product-list"
              itemIdPrefix="product"
              direction="vertical"
              list={musicList}
              onDropEndCallback={onDropEndMusics}
            >
              {(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={musicList?.length === 1}
                  >
                    <MusicCardMemo
                      module={module}
                      titleShortcut
                      disableDragDrop={module.items.length <= 1}
                      index={productIndex}
                      disableDrag={musicList?.length === 1}
                      item={item}
                      onEdit={onBeforeEditProduct}
                      onDelete={onDeleteMusic}
                      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."
                    />
                  </PortalComponent>
                ) : (
                  <></>
                )
              }}
            </DragDropContext>
          </React.Fragment>
        )}
        {!active && musicList.length > 2 && (
          <div className="d--flex justify__content--end align__items--center m__t--20 cursor-pointer">
            <Text preset="medium14" className="opacity-6">
              +{musicList.length - 2} More
            </Text>
          </div>
        )}
      </ModuleEditor>
      <AddProfileSmartPodcast
        isEdit={musicEditState.isEdit}
        music={musicEditState.music}
        onSetVisible={handleSetVisible}
        visible={visible}
        onFinish={onSaveProductCallback}
        onConnectSpotify={handleConnectSpotify}
      />
    </React.Fragment>
  )
}

export default React.memo(ModulePodcast)
