import { makeComponentProps } from '@/composables/component'
import { computed, ref, watch, watchEffect } from 'vue'

import { UIcon } from '@/components/UIcon/UIcon'
import { UListItem } from '@/components/UListItemGroup/UListItem'

import { genericComponent, propsFactory, useRender } from '@/utils'

export const makeUListItemGroupProps = propsFactory(
  {
    disabled: {
      type: Boolean,
      default: false,
    },
    position: {
      type: String,
      default: 'bottom',
    },
    type: {
      type: String,
      default: 'default',
    },
    color: {
      type: String,
      default: 'transparent',
    },
    listItems: {
      type: Array<{
        title: string
        badge: number
        itemId: string
        prependIcon: string
      }>,
      required: true,
    },
    currentItemId: String,
    prependIcon: String,
    ...makeComponentProps(),
  },
  'UListItemGroup'
)

export type UListItemGroupSlots = {
  default: never
  header: never
}

export const UListItemGroup = genericComponent<UListItemGroupSlots>()({
  name: 'UListItemGroup',

  props: makeUListItemGroupProps(),

  emits: {
    click: (e: MouseEvent) => true,
    currentItemId: (value: string) => true,
  },

  setup(props, { emit, slots }) {
    const isActive = ref(false)
    const isHover = ref(false)
    const itemsListRef = ref<HTMLElement | null>(null)

    type listItem = {
      title: string
      badge: number
      itemId: string
      prependIcon: string
    }

    const getListItems = (): listItem[] => {
      const listItems: listItem[] = props.listItems

      if (Array.isArray(listItems)) {
        const updatedItems = listItems.map((item) => {
          if (item.title && item.itemId && item.prependIcon && item.badge) {
            return item
          } else {
            return {
              title: item.title || '',
              badge: item.badge || 0,
              itemId: item.itemId || '',
              prependIcon: item.prependIcon || '',
            }
          }
        })

        const filteredItems = updatedItems.filter((item) => {
          return (
            item.title !== '' ||
            item.badge !== 0 ||
            item.itemId !== '' ||
            item.prependIcon !== ''
          )
        })

        return filteredItems
      } else {
        return []
      }
    }

    function changeCurrentIndex(id: string) {
      if (props.disabled) return
      emit('currentItemId', id)
    }

    function onListItemClick(e: MouseEvent) {
      if (props.disabled) return
      emit('click', e)
    }

    const renderListItems = (): JSX.Element[] => {
      const filteredItems = getListItems()

      return filteredItems.map((item, index) => (
        <UListItem
          prependIcon={item.prependIcon}
          isActive={props.currentItemId === item.itemId}
          badge={item.badge}
          itemId={item.itemId}
          key={index}
          onCurrentItemId={changeCurrentIndex}
          onClick={onListItemClick}
        >
          {item.title}
        </UListItem>
      ))
    }

    const navItemClasses = computed(() => ({
      'flex items-center p-3 w-full rounded-md overflow-hidden': true,
      ...(!props.disabled && {
        'cursor-pointer active:shadow-xs-btn active:shadow-gray-100': true,
      }),
      ...(props.disabled && {
        'cursor-not-allowed': true,
      }),
      ...(isActive.value === false &&
        !props.disabled && {
          'active:bg-transparent hover:bg-gray-50': true,
        }),
      ...(isActive.value === true &&
        !props.disabled && {
          'bg-gray-200 hover:bg-gray-100 active:bg-gray-50': true,
        }),
      ...(props.type !== 'small' && {
        'justify-between': true,
      }),
      ...(props.type === 'small' &&
        !props.disabled && {
          'h-48 max-w-[48px] flex-shrink-none justify-center': true,
        }),
    }))

    const navItemTextClasses = computed(() => ({
      'text-text-md font-semibold select-none whitespace-nowrap': true,
      ...(isHover.value === false && {
        'text-gray-700': true,
      }),
      ...(isHover.value === true && {
        'text-gray-700': true,
      }),
      ...(isActive.value === true && {
        'text-gray-700': true,
      }),
    }))

    const chevronIconClasses = computed(() => ({
      'transition-transform': true,
      ...(isActive.value === true &&
        props.position === 'bottom' &&
        !props.disabled && {
          'rotate-180': true,
        }),
      ...(isActive.value === true &&
        props.position !== 'bottom' &&
        !props.disabled && {
          'opacity-0': true,
        }),
    }))

    const itemsListHeight = () => {
      const element = itemsListRef.value
      if (element) {
        return (element.scrollHeight + 16).toString()
      }
      return '0'
    }

    function getParentWidth() {
      const element = itemsListRef.value
      if (element) {
        let parentElement = element.parentElement
        while (
          parentElement &&
          getComputedStyle(parentElement).position !== 'relative'
        ) {
          parentElement = parentElement.parentElement
        }

        if (parentElement) {
          return parentElement.clientWidth
        } else {
          return 0
        }
      } else {
        return 0
      }
    }

    watch(isActive, (newValue) => {
      if (
        getListItems().length !== 0 &&
        props.position == 'bottom' &&
        !props.disabled
      ) {
        const element = itemsListRef.value
        if (element) {
          if (newValue) {
            element.style.transition =
              'max-height 0.15s ease-in-out, padding 0.15s ease-in-out'
            element.style.paddingTop = '8px'
            element.style.paddingBottom = '8px'
            element.style.maxHeight = `${itemsListHeight()}px`
          } else {
            element.style.transition =
              'max-height 0.15s ease-in-out, padding 0.15s ease-in-out'
            element.style.paddingTop = ''
            element.style.paddingBottom = ''
            element.style.maxHeight = ''
          }
        }
      }
      if (
        getListItems().length !== 0 &&
        props.position == 'right' &&
        !props.disabled
      ) {
        const element = itemsListRef.value
        if (element) {
          if (newValue) {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.position = 'absolute'
            element.style.top = '0'
            element.style.left = `${getParentWidth()}px`
            element.style.overflowY = `visible`
            element.style.visibility = `visible`
            element.style.paddingTop = '36px'
            element.style.opacity = `1`
            element.style.maxHeight = `100%`
            element.style.height = `100%`
          } else {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.opacity = `0`
            element.style.visibility = `visible`
            setTimeout(() => {
              element.style.visibility = 'hidden'
              element.style.transition = ''
            }, 150)
          }
        }
      }
      if (
        getListItems().length !== 0 &&
        props.position == 'left' &&
        !props.disabled
      ) {
        const element = itemsListRef.value
        if (element) {
          if (newValue) {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.position = 'absolute'
            element.style.top = '0'
            element.style.right = `${getParentWidth()}px`
            element.style.overflowY = `visible`
            element.style.visibility = `visible`
            element.style.paddingTop = '36px'
            element.style.opacity = `1`
            element.style.maxHeight = `100%`
            element.style.height = `100%`
          } else {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.opacity = `0`
            element.style.visibility = `visible`
            setTimeout(() => {
              element.style.visibility = 'hidden'
              element.style.transition = ''
            }, 150)
          }
        }
      }
      if (
        getListItems().length !== 0 &&
        props.position !== 'left' &&
        props.type == 'small' &&
        !props.disabled
      ) {
        const element = itemsListRef.value
        if (element) {
          if (newValue) {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.position = 'absolute'
            element.style.top = '0'
            element.style.left = `76px`
            element.style.width = `${getParentWidth() - 76}px`
            element.style.overflowY = `visible`
            element.style.visibility = `visible`
            element.style.paddingTop = '36px'
            element.style.opacity = `1`
            element.style.maxHeight = `100%`
            element.style.height = `100%`
          } else {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.opacity = `0`
            element.style.visibility = `visible`
            element.style.paddingTop = '36px'
            setTimeout(() => {
              element.style.visibility = 'hidden'
              element.style.transition = ''
            }, 150)
          }
        }
      }
      if (
        getListItems().length !== 0 &&
        props.position === 'left' &&
        props.type == 'small' &&
        !props.disabled
      ) {
        const element = itemsListRef.value
        if (element) {
          if (newValue) {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.position = 'absolute'
            element.style.top = '0'
            element.style.right = `76px`
            element.style.width = `${getParentWidth() - 76}px`
            element.style.overflowY = `visible`
            element.style.visibility = `visible`
            element.style.paddingTop = '36px'
            element.style.opacity = `1`
            element.style.maxHeight = `100%`
            element.style.height = `100%`
          } else {
            element.style.transition =
              'transform 0.15s ease-in-out, opacity 0.15s ease-in-out'
            element.style.position = 'absolute'
            element.style.opacity = `0`
            element.style.visibility = `visible`
            setTimeout(() => {
              element.style.visibility = 'hidden'
              element.style.transition = ''
            }, 150)
          }
        }
      }
    })

    watchEffect(() => {
      if (props.type !== 'small') {
        const element = itemsListRef.value
        if (element) {
          element.style.transition = ''
          element.style.opacity = ''
          element.style.visibility = ''
          element.style.position = ''
          element.style.overflowY = ''
          element.style.paddingTop = ''
          element.style.width = ''
        }
      }
    })

    const itemsListClasses = computed(() => ({
      // eslint-disable-next-line max-len
      'w-calc-100%-plus-8px flex flex-col gap-1 px-1 ml-[-4px] overflow-y-hidden transition-max-height max-h-0 select-none':
        true,
      ...(props.position !== 'bottom' && {
        'opacity-0': true,
      }),
      ...(props.type === 'small' &&
        props.position !== 'bottom' && {
          'w-[0px] px-3': true,
        }),
      [`bg-${props.color}`]: true,
    }))

    const subTitleClasses = computed(() => ({
      'text-md text-gray-900 px-3 pb-4 font-medium': true,
    }))

    const prependIconColor = () => {
      if (isActive.value === true || isHover.value === true) {
        return 'gray-500'
      }
      return 'gray-500'
    }

    const chevronIconColor = () => {
      if (
        (isActive.value === true || isHover.value === true) &&
        !props.disabled
      ) {
        return 'gray-400'
      }
      return 'gray-500'
    }

    useRender(() => (
      <div class="w-full">
        <div
          onMouseover={() => (isHover.value = true)}
          onMouseleave={() => (isHover.value = false)}
          onClick={() => (isActive.value = !isActive.value)}
          class={[navItemClasses.value, 'item']}
        >
          <div class="flex gap-3 items-center">
            {props.prependIcon ? (
              <UIcon
                color={prependIconColor()}
                size="24"
                icon={`$${props.prependIcon}`}
              ></UIcon>
            ) : null}
            {slots.default && props.type !== 'small' && (
              <div class={navItemTextClasses.value}>{slots.default?.()}</div>
            )}
          </div>

          {getListItems().length !== 0 && props.type !== 'small' ? (
            <div class={chevronIconClasses.value}>
              <UIcon
                color={chevronIconColor()}
                size="20"
                icon={`$chevronDown`}
              ></UIcon>
            </div>
          ) : null}
        </div>
        <div ref={itemsListRef} class={itemsListClasses.value}>
          {slots.default && props.type === 'small' && (
            <div class={subTitleClasses.value}>{slots.default?.()}</div>
          )}
          {renderListItems()}
        </div>
      </div>
    ))

    return {
      isActive,
    }
  },
})

export type UListItemGroup = InstanceType<typeof UListItemGroup>
