import './ModuleEditor.scss'
import React, {
  useState,
  useCallback,
  FocusEvent,
  MouseEvent,
  ChangeEvent,
  KeyboardEvent,
  useMemo,
  useEffect
} from 'react'
import { useHistory } from 'react-router-dom'
import { useAutoSave } from 'hooks/useAutoSave'
import PanelCollapse from 'components/PanelCollapse'
import { Row, Tooltip } from 'antd'
import Button from 'antd/lib/button'
import { Col } from 'antd/lib/grid'
import useBreakpoint from 'antd/lib/grid/hooks/useBreakpoint'
import Input from 'antd/lib/input'
import Popover from 'antd/lib/popover'
import classNames from 'classnames'
import DragDropButton from 'components/Button/DragDropButton'
import ConfirmDeleteModal from 'components/ConfirmDeleteModal'
import { ConfirmDeleteModalProps } from 'components/ConfirmDeleteModal/ConfirmDeleteModal'
import { Icon } from 'components/Icon'
import LabelTooltip from 'components/LabelTooltip/LabelTooltip'
import Loading from 'components/Loading'
import StripeConnectBox from 'components/StripeConnectBox'
import { Paragraph, Text } from 'components/Typography'
import { useModules } from 'hooks/useModules'
import {
  TalentModuleMixItem,
  TalentProfileModule,
  TalentProfileModuleObj,
  BaseItem,
  DataCaptureActivationItemNew
} from 'models/talent/talent-profile-module.model'

import {
  ModuleType,
  ShopifyStoreTypes,
  RyeShopifyStoreTypes
} from '@komi-app/shared-types'

import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'
import { isMobile } from 'react-device-detect'
import { MENU_LINKS } from 'routes'
import './ModuleEditor.scss'
import ModuleEditorAction from './ModuleEditorAction'
import { closeExpandModule } from 'redux/Talent/selector'
import { useSelector } from 'react-redux'
import cloneDeep from 'lodash/cloneDeep'
import includes from 'lodash/includes'
import filter from 'lodash/filter'
import { updateCloseExpandActions } from 'redux/Talent/actions'
import { useDispatch } from 'react-redux'
import ModuleVisiblityEditor from './ModuleVisiblityEditor'
import ModuleVisibilityToggle from './ModuleVisibilityToggle'
import { FLAGS, IfFeature, useFeatureIsOn } from '@komi-app/flags-sdk'
import { useWindowSize } from '../../../hooks'
import When from '@komi-app/when'
import { Button as CreatorButton, Semantic } from '@komi-app/creator-ui'
import List from 'antd/lib/list'
interface ModuleEditorProps<T> {
  module: TalentProfileModule<T>
  banner?: React.ReactNode
  showStripeWarning?: boolean
  disableModuleVisibility?: boolean
  onEditBandsintownLink?: () => void
  onEditSeatedLink?: () => void
  onEditShopMyShelf?: () => void
  onEditShopList?: () => void
  onEditYoutube?: () => void
  onEditDataCapture?: (dataCapture: DataCaptureActivationItemNew) => void
  dragHandleProps?: DraggableProvidedDragHandleProps
  children?: any
  InfoTooltip?: React.ReactNode
  confirmDeleteModalProps?: ConfirmDeleteModalProps
}

const MAX_NAME_LENGTH = 33
const ModuleEditor: React.FC<ModuleEditorProps<any>> = ({
  module,
  banner,
  dragHandleProps,
  showStripeWarning = false,
  onEditBandsintownLink,
  onEditSeatedLink,
  onEditShopList,
  children,
  InfoTooltip,
  confirmDeleteModalProps,
  onEditShopMyShelf,
  onEditYoutube,
  onEditDataCapture,
  disableModuleVisibility = false
}) => {
  const dispatch = useDispatch()
  const [moduleNameState, setModuleNameState] = useState<string>('')
  const [showModuleAction, setShowModuleAction] = useState(false)
  const [showVisibilityAction, setShowVisibilityAction] = useState(false)
  const [showConfirmModal, setShowConfirmModal] = useState(false)
  const [visibleUnGroup, setVisibleUnGroup] = useState(false)
  const [moduleDeleteConfirm, setModuleDeleteConfirm] = useState<
    TalentProfileModule<TalentModuleMixItem>
  >(() => module)
  const screens = useBreakpoint()
  const mobile = isMobile || screens['xs']
  const history = useHistory()
  const { onForceSave } = useAutoSave()
  const {
    selectedModules,
    onChangeSelected,
    onUnGroup,
    setModule,
    setSelectedModules,
    modules,
    removeModule
  } = useModules()

  const { width } = useWindowSize()

  const isMobileStyleChangesEnabled = width && width <= 768

  const isTemplatesV2Enabled = useFeatureIsOn(
    FLAGS.FEAT_SB_447_MODULE_TEMPLATES
  )

  const isQuickDeleteEnabled = module.template

  const closeExpand = useSelector(closeExpandModule)
  useEffect(() => {
    setModuleNameState(module.name || '')
  }, [module])

  const isEdit = module.isEdit

  const isDisableExpand = useMemo(
    () => !module.items || !module.items.length,
    [module]
  )

  const isDisableDrop = useMemo(() => {
    if (module.groupId) {
      const group = modules.find((el: any) => el.id === module.groupId)
      return group?.items.length <= 1
    }
    return modules.length <= 1
  }, [modules, module])

  const onEditCallback = useCallback(
    (moduleEdit: TalentProfileModule<BaseItem>) => {
      setModule(moduleEdit)
    },
    [setModule]
  )

  const onDeleteCallback = useCallback(
    (moduleDel: TalentProfileModule<BaseItem>) => {
      removeModule(moduleDel)
    },
    [removeModule]
  )

  const handleUpdateModuleName = () => {
    let newModuleName = module.name || ''
    let isUpdate = false

    newModuleName = moduleNameState

    if (module.name !== newModuleName) {
      isUpdate = true
    }

    onEditCallback({
      ...module,
      name: newModuleName,
      isEdit: false,
      isUpdate: isUpdate,
      visible: module.visible ?? true
    })
  }

  const onChangeInput = (event: ChangeEvent<HTMLInputElement>) => {
    event.stopPropagation()
    setModuleNameState(
      event.target.value.length <= MAX_NAME_LENGTH
        ? event.target.value
        : moduleNameState
    )
  }

  const onBlurInput = (event: FocusEvent<HTMLInputElement>) => {
    event.stopPropagation()
    handleUpdateModuleName()
  }

  const onClickInput = (event: MouseEvent<HTMLInputElement>) => {
    event.stopPropagation()
  }

  const onEditInput = (event: MouseEvent<HTMLInputElement>) => {
    event.stopPropagation()
    onEditCallback({ ...module, isEdit: true })
  }

  const onKeyUpInput = (event: KeyboardEvent<HTMLInputElement>) => {
    event.stopPropagation()
    if (event.key === 'Enter') {
      handleUpdateModuleName()
    }
  }

  const onEditModule = (
    moduleEdit: TalentProfileModule<TalentModuleMixItem>
  ) => {
    onEditCallback({ ...moduleEdit, isEdit: true })
  }

  const onSelectModule = (module: TalentProfileModule<TalentModuleMixItem>) => {
    setShowModuleAction(false)

    if (!selectedModules.some((el: any) => el.id === module.id)) {
      setSelectedModules([...selectedModules, module])
    }
  }

  const onBeforeRemove = (
    moduleDel: TalentProfileModule<TalentModuleMixItem>
  ) => {
    if (
      selectedModules.some((module: TalentProfileModule<TalentModuleMixItem>) =>
        [module.id, module.groupId].includes(moduleDel.id)
      )
    ) {
      const newSelected = selectedModules.filter(
        (module: TalentProfileModule<TalentModuleMixItem>) =>
          ![module.id, module.groupId].includes(moduleDel.id)
      )
      setSelectedModules(newSelected)
    }
  }
  const onDeleteModule = (
    moduleDel: TalentProfileModule<TalentModuleMixItem>
  ) => {
    if (!moduleDel.items || !moduleDel.items.length) {
      onDeleteCallback(moduleDel as TalentProfileModule<TalentModuleMixItem>)
      setModuleDeleteConfirm(new TalentProfileModuleObj())
      onBeforeRemove(moduleDel)
    } else {
      setShowConfirmModal(true)
      setModuleDeleteConfirm(moduleDel)
    }
  }

  const onDeleteModuleConfirm = () => {
    onDeleteCallback(
      moduleDeleteConfirm as TalentProfileModule<TalentModuleMixItem>
    )
    setModuleDeleteConfirm(new TalentProfileModuleObj())
    onBeforeRemove(moduleDeleteConfirm)
    toggleConfirmModal(false)
  }

  const toggleExpand = (value: boolean) => {
    onEditCallback({ ...module, expand: value })
    let dataCloseExpand = closeExpand ? cloneDeep(closeExpand) : []
    if (value) {
      dataCloseExpand = filter(dataCloseExpand, function (o) {
        return o !== module?.id
      })
    } else {
      dataCloseExpand.push(module?.id as string)
    }
    dispatch(updateCloseExpandActions(dataCloseExpand))
  }

  const toggleConfirmModal = (value: boolean) => {
    setShowConfirmModal(value)
  }

  const handleEditBandsintownLink = () => {
    setShowModuleAction(false)
    onEditBandsintownLink?.()
  }
  const handleEditSeatedLink = () => {
    setShowModuleAction(false)
    onEditSeatedLink?.()
  }

  const manageShopifyStores = useCallback(() => {
    onForceSave()
    setTimeout(() => {
      history.push(`${MENU_LINKS.ACCOUNT_SETTINGS}#Shopify`)
    }, 250)
  }, [])

  const onManageRyeShopifyStore = useCallback(() => {
    onForceSave()
    setTimeout(() => {
      history.push(`/admin/settings/integrations`)
    }, 250)
  }, [])

  // Not ideal, but because the items are stored as json documents in the db,
  // we'd have to modify the json during the visibility migration to set visible default to true
  // If it's already been set this will just pass over it
  const selected = useMemo(() => {
    if (module.type === ModuleType.GROUP) {
      return module.items.every(item =>
        selectedModules.some((el: any) => el.id === item.id)
      )
    }
    return selectedModules.some((item: any) => item.id === module.id)
  }, [module, selectedModules])
  const isUnCheckGroup = useMemo(() => {
    return (
      module.type === ModuleType.GROUP &&
      !selected &&
      module.items.some(item =>
        selectedModules.some((el: any) => el.id === item.id)
      )
    )
  }, [module, selected, selectedModules])
  const handleClickUnGroup = useCallback(() => {
    setVisibleUnGroup(true)
  }, [])
  const onUnGroupConfirm = useCallback(() => {
    onUnGroup(module.items)
    setVisibleUnGroup(false)
  }, [onUnGroup, module.items])

  const handleVisibilityChanged = (
    visible: boolean,
    showTitle: boolean,
    items: TalentModuleMixItem[]
  ) => {
    onEditCallback({ ...module, isUpdate: true, visible, showTitle, items })
  }

  const onQuickDeleteClicked = useCallback(
    (e: React.MouseEvent<HTMLButtonElement>) => {
      e.stopPropagation()
      e.preventDefault()
      onDeleteModule(module)
    },
    [onDeleteModule, module]
  )

  const maxLength = useMemo(() => {
    if (
      [
        ModuleType.BANDSINTOWN,
        ModuleType.SHOPIFY,
        ModuleType.RYE_SHOPIFY,
        ModuleType.SHOP_LIST,
        ModuleType.SHOP_MY_SHELF,
        ModuleType.YOUTUBE,
        ModuleType.YOUTUBE_COLLECTION,
        ModuleType.YOUTUBE_SHORT,
        ModuleType.YOUTUBE_VIDEO
      ].includes(module.type as any) &&
      module.groupId
    ) {
      return 18
    }
    if (mobile) {
      return 20
    }
    return 33
  }, [module, mobile])
  const renderTag = useCallback(() => {
    if (ShopifyStoreTypes.includes(module.type as ModuleType)) {
      return (
        <div className="shopify-tag m__l--16 bg--blue p__x--8 p__y--2 bo__radius--16">
          <Text preset="medium14" className="text--white">
            Shopify
          </Text>
        </div>
      )
    }
    if (RyeShopifyStoreTypes.includes(module.type as ModuleType)) {
      return (
        <div className="shopify-tag m__l--16 bg--blue p__x--8 p__y--2 bo__radius--16">
          <Text preset="medium14" className="text--white">
            Shopify
          </Text>
        </div>
      )
    }
    let tag = ''
    let desktopOnly = true
    switch (module.type) {
      case ModuleType.BANDSINTOWN:
        tag = 'Bandsintown'
        break
      case ModuleType.SEATED:
        tag = 'Seated'
        break
      case ModuleType.SHOP_MY_SHELF:
        tag = 'Shop My'
        break
      case ModuleType.SHOP_LIST:
        tag = 'Shoplist'
        break
      case ModuleType.YOUTUBE:
      case ModuleType.YOUTUBE_COLLECTION:
      case ModuleType.YOUTUBE_VIDEO:
        tag = 'YouTube'
        break
      case ModuleType.YOUTUBE_SHORT:
        tag = 'Shorts'
        break
      case ModuleType.TIKTOK_VIDEO:
      case ModuleType.TIKTOK_AUTOMATION:
        tag = 'TikTok'
        break
      case ModuleType.INSTAGRAM_REEL:
        tag = 'Instagram'
        break

      default:
        break
    }

    if (isTemplatesV2Enabled && module.template) {
      tag = 'Template'
      desktopOnly = false
    }

    if (tag) {
      return (
        <div
          className={classNames(
            'shopify-tag m__l--16 bg--blue p__x--8 p__y--2 bo__radius--16',
            { desktop__only: desktopOnly }
          )}
        >
          <Text preset="medium14" className="text--white">
            {tag}
          </Text>
        </div>
      )
    }
    return null
  }, [module.type, module.template, isTemplatesV2Enabled])
  return (
    <div data-testid="module-editor--music">
      <ConfirmDeleteModal
        show={showConfirmModal}
        toggleModal={toggleConfirmModal}
        cancelLabel="No Thanks!"
        confirmLabel="Delete"
        title="Are you sure you want to delete this module?"
        description={
          'This module will be deleted and you can’t undo this action.'
        }
        width={522}
        handleConfirm={onDeleteModuleConfirm}
        {...confirmDeleteModalProps}
      />
      <ConfirmDeleteModal
        show={visibleUnGroup}
        toggleModal={setVisibleUnGroup}
        cancelLabel="No Thanks!"
        confirmLabel="Ungroup"
        title="Are you sure you want to ungroup these modules?"
        description={
          'The modules will be ungrouped and displayed individually. You can group them again at any time.'
        }
        handleConfirm={onUnGroupConfirm}
      />

      <div
        className={classNames('module-editor__wrapper', {
          'module-editor__wrapper--with-bottom-actions': isQuickDeleteEnabled
        })}
        // onFocus={onFocus}
        // onBlur={onBlur}
        // onKeyDown={onKeyDown}
      >
        <PanelCollapse
          type={module.type}
          expandDisable={isDisableExpand}
          // expand={module.expand}
          expand={!includes(closeExpand, module.id)}
          toggleExpand={toggleExpand}
          selected={selected}
          onChangeSelected={onChangeSelected(module)}
          isUnCheckGroup={isUnCheckGroup}
          title={
            isEdit ? (
              <React.Fragment>
                <div
                  className="module-editor__title-input"
                  data-testid="module-editor--title-input-wrapper"
                >
                  <Input
                    className="module-editor__title--input fullwidth"
                    data-testid="module-editor--title-input"
                    bordered={false}
                    autoFocus
                    defaultValue={module.name}
                    placeholder={
                      module.type === ModuleType.GROUP
                        ? 'Enter Your Group Name'
                        : 'Enter Module Name'
                    }
                    value={moduleNameState}
                    onBlur={onBlurInput}
                    onClick={onClickInput}
                    onChange={onChangeInput}
                    onKeyUp={onKeyUpInput}
                  />
                  <Text
                    preset="regular12"
                    className="module-editor__title--count"
                  >
                    ({moduleNameState.length}/33 characters)
                  </Text>
                </div>
              </React.Fragment>
            ) : (
              <Row wrap={false} align="middle" className="module-title-row">
                <Col flex="1">
                  <Button
                    data-testid="module-editor--title"
                    className="p--0"
                    type="link"
                    onClick={onEditInput}
                  >
                    <LabelTooltip
                      className={classNames('module-editor__title--label', {
                        'opacity--03': !module.name?.length,
                        'opacity--04': module.groupId && !module.showTitle
                      })}
                      preset={!module.name?.length ? 'medium20' : 'semibold18'}
                      label={
                        module.name ||
                        (module.type === ModuleType.GROUP
                          ? 'Enter Your Group Name'
                          : 'Enter Module Name')
                      }
                      maxLength={maxLength}
                    />
                  </Button>
                </Col>
                <Col>{InfoTooltip}</Col>
                {renderTag()}
              </Row>
            )
          }
          isEdit={isEdit}
          action={
            <Row
              className="module-editor__actions"
              align="middle"
              justify="end"
            >
              <When
                value={width && width > 768 && module.type === ModuleType.GROUP}
                then={
                  <Col>
                    <Row align="middle">
                      <Col className="group-label">
                        <Paragraph className="opacity--06" preset="medium14">
                          {`${module.items.length} module${
                            module.items.length > 1 ? 's' : ''
                          } added`}
                        </Paragraph>
                      </Col>
                      <Col onClick={handleClickUnGroup} className="m__l--8">
                        <Tooltip
                          style={{ zIndex: 9999999 }}
                          overlayClassName="group-module-tooltip"
                          placement="top"
                          title={`Ungroup`}
                        >
                          <div
                            className="height--24 cursor-pointer"
                            data-testid="ungroup-button"
                          >
                            <Icon name="ungroup" />
                          </div>
                        </Tooltip>
                      </Col>
                    </Row>
                  </Col>
                }
              />
              {
                // If the module is in a group, show the visibility drop down
                module.groupId ? (
                  <Col
                    onClick={event => event.stopPropagation()}
                    className={
                      isMobileStyleChangesEnabled ? 'm__l--8' : 'm__l--16'
                    }
                    data-testid="module-editor--visibility"
                  >
                    <Popover
                      visible={showVisibilityAction}
                      placement="bottomRight"
                      overlayClassName="module-editor-overlay"
                      arrowContent={null}
                      content={
                        <ModuleVisiblityEditor
                          module={module}
                          toggleVisible={setShowModuleAction}
                          onEditModule={onEditModule}
                          onVisiblityChanged={handleVisibilityChanged}
                        />
                      }
                      trigger={['click']}
                      onVisibleChange={setShowVisibilityAction}
                    >
                      <Button
                        data-testid="module-editor--options-icon"
                        className={classNames(
                          'p--0 d--flex align__items--center',
                          {
                            'height--24': isMobileStyleChangesEnabled
                          }
                        )}
                        type="link"
                        disabled={
                          disableModuleVisibility ||
                          modules.find((x: any) => x.id === module.groupId)
                            ?.visible === false
                        }
                      >
                        <Icon
                          name={
                            disableModuleVisibility ||
                            modules.find((x: any) => x.id === module.groupId)
                              ?.visible === false
                              ? 'closed-eye-inactive'
                              : module.visible
                                ? 'open-eye'
                                : 'closed-eye'
                          }
                        />
                      </Button>
                    </Popover>
                  </Col>
                ) : (
                  // If the module isn't a group, show the visibility button
                  <Col
                    onClick={event => event.stopPropagation()}
                    className={
                      isMobileStyleChangesEnabled ? 'm__l--8' : 'm__l--16'
                    }
                    data-testid="module-editor--visibility"
                  >
                    <ModuleVisibilityToggle
                      module={module}
                      disabled={disableModuleVisibility}
                    />
                  </Col>
                )
              }

              <Col
                onClick={event => event.stopPropagation()}
                className={isMobileStyleChangesEnabled ? 'm__l--8' : 'm__l--16'}
                data-testid="module-editor--options"
              >
                <Popover
                  visible={showModuleAction}
                  placement="bottomRight"
                  overlayClassName="module-editor-overlay"
                  arrowContent={null}
                  content={
                    <ModuleEditorAction
                      module={module}
                      onEdit={onEditModule}
                      onSelectModule={onSelectModule}
                      onDelete={onDeleteModule}
                      toggleVisible={setShowModuleAction}
                      onEditBandsintownLink={handleEditBandsintownLink}
                      onEditSeatedLink={handleEditSeatedLink}
                      onEditShopMyShelf={onEditShopMyShelf}
                      onEditShopList={onEditShopList}
                      onManageShopifyStore={manageShopifyStores}
                      onManageRyeShopifyStore={onManageRyeShopifyStore}
                      onEditYoutubeCollection={onEditYoutube}
                      onEditDataCapture={onEditDataCapture}
                    />
                  }
                  trigger={['click']}
                  onVisibleChange={setShowModuleAction}
                >
                  <Button
                    data-testid="module-editor--options-icon"
                    className={classNames('p--0 d--flex align__items--center', {
                      'height--24': isMobileStyleChangesEnabled
                    })}
                    type="link"
                    // onClick={() => setShowModuleAction(true)}
                  >
                    <Icon name="more" />
                  </Button>
                </Popover>
              </Col>
              <Col
                data-testid="module-editor--drag-drop"
                className={
                  isMobileStyleChangesEnabled ? 'height--24 m__l--8' : undefined
                }
              >
                <DragDropButton
                  style={{ paddingRight: 0 }}
                  dragType="vertical"
                  dragHandleProps={dragHandleProps}
                  disabled={isDisableDrop}
                  onClick={event => event.stopPropagation()}
                />
              </Col>
            </Row>
          }
        >
          {module.isLoading && <Loading blur />}
          {children}
          {showStripeWarning && <StripeConnectBox className="m__t--24" />}
          {banner}
        </PanelCollapse>
        {isQuickDeleteEnabled && (
          <div className="module-editor-bottom-actions">
            <CreatorButton
              label="Delete"
              semantic={Semantic.SECONDARY}
              size="small"
              onClick={onQuickDeleteClicked}
            />
          </div>
        )}
      </div>
    </div>
  )
}

export default React.memo(ModuleEditor)
