import { makeComponentProps } from '@/composables/component'
import { makeTagProps } from '@/composables/tag'

import { ExtractPropTypes, computed } from 'vue'
import { genericComponent, propsFactory } from '@/utils'
import ColorName from '@/types/colors'
import { UIcon, UAvatar } from '../../components'
import Sizes from '@/types/sizes'

export const makeUBadgeProps = propsFactory(
  {
    size: {
      type: String,
      default: 'sm',
      required: false,
    },
    type: {
      type: String,
      default: 'default',
      required: false,
    },
    color: {
      type: String,
      default: 'primary',
      required: false,
    },
    avatarImagePath: {
      type: String,
      required: false,
    },
    avatarText: {
      type: String,
      required: false,
    },
    arrowUp: {
      type: Boolean,
      required: false,
    },
    arrowRight: {
      type: Boolean,
      required: false,
    },
    plus: {
      type: Boolean,
      required: false,
    },

    ...makeComponentProps(),
    ...makeTagProps(),
  },
  'UBadge'
)

export type UBadgeProps = ExtractPropTypes<typeof makeUBadgeProps>

export type UBadgeSlots = {
  default: never
}

export const UBadge = genericComponent<UBadgeSlots>()({
  name: 'UBadge',

  props: makeUBadgeProps(),

  emits: {
    click: (e: MouseEvent) => true,
    appendClick: (e: MouseEvent) => true,
    prependClick: (e: MouseEvent) => true,
  },

  setup(props, { emit, slots }) {
    const bgColor = computed(() => {
      let color = ''
      if (props.color === 'gray' && props.type === 'default') {
        color = 'gray-100'
      } else if (props.color !== 'gray' && props.type === 'default') {
        color = props.color + '-50'
      } else {
        color = 'transparent'
      }
      return color as ColorName
    })

    const borderColor = computed(() => {
      return props.type === 'outlined'
        ? `border-1.5 border-${textColor.value}`
        : ''
    })

    const arrowColor = computed(() => {
      return `${props.color}-500` as ColorName
    })

    const textSizes = computed(() => {
      let text = ''
      if (props.size === 'sm') {
        text = 'text-text-xs'
      } else if (props.size === 'md' || props.size === 'lg') {
        text = 'text-text-sm'
      }
      return text
    })

    const textColor = computed(() => {
      return props.color + '-700'
    })

    const avatarPaddingClasses = computed(() => ({
      ['pr-px']: props.size === 'sm',
      ['pr-0']: props.size === 'md' || props.size === 'lg',
    }))

    const arrowUpPaddingClasses = computed(() => ({
      ['pl-0.6']: props.size === 'sm',
      ['pl-1']: props.size === 'md' || props.size === 'lg',
    }))

    const arrowRightPaddingClasses = computed(() => ({
      ['pr-0.6']: props.size === 'sm',
      ['pr-0.5']: props.size === 'md',
      ['pr-1']: props.size === 'lg',
    }))

    const plusPaddingClasses = computed(() => ({
      ['py-1 px-1']: props.size === 'sm',
      ['py-1.5 px-1.5']: props.size === 'md',
      ['py-2 px-2']: props.size === 'lg',
    }))

    const labelPaddingClasses = computed(() => ({
      ['px-1.3']:
        (props.size === 'sm' &&
          (props.avatarText || props.avatarImagePath) &&
          !props.arrowUp) ||
        ((!props.avatarText || !props.avatarImagePath) && !props.arrowUp),
      ['px-1.5']:
        ((props.size === 'md' || props.size === 'lg') &&
          (props.avatarText || props.avatarImagePath) &&
          !props.arrowUp) ||
        ((!props.avatarText || !props.avatarImagePath) && !props.arrowUp),
      ['pr-1.3 pl-1']:
        props.size === 'sm' &&
        (!props.avatarText || !props.avatarImagePath) &&
        props.arrowUp,
      ['pr-1.5 pl-1']:
        (props.size === 'md' || props.size === 'lg') &&
        (!props.avatarText || !props.avatarImagePath) &&
        props.arrowUp,
      ['pl-1.3 pr-1']: props.size === 'sm' && props.arrowRight,
      ['pl-1.5 pr-1']:
        (props.size === 'md' || props.size === 'lg') && props.arrowRight,
    }))

    const containerPaddingClasses = computed(() => ({
      ['py-0.5 px-0.6']: props.size === 'sm',
      ['py-0.5 px-1']: props.size === 'md',
      ['py-1 px-1.5']: props.size === 'lg',
    }))

    const classes = computed(() => {
      return `bg-${bgColor.value} w-fit ${textSizes.value} text-${textColor.value}
      rounded-16 flex justify-center items-center ${borderColor.value} font-medium`
    })

    const handleAppendClick = (newValue: any) => {
      emit('appendClick', newValue)
    }

    const handlePrependClick = (newValue: any) => {
      emit('prependClick', newValue)
    }

    return () => (
      <div
        class={[classes.value, containerPaddingClasses.value]}
        onClick={(e) => emit('click', e)}
      >
        {props.avatarImagePath ? (
          <div class={avatarPaddingClasses.value} onClick={handlePrependClick}>
            <UAvatar
              size={Sizes.xs}
              imagePath={props.avatarImagePath}
            ></UAvatar>
          </div>
        ) : null}
        {props.avatarText ? (
          <div class={avatarPaddingClasses.value} onClick={handlePrependClick}>
            <UAvatar size={Sizes.xs} avatarIcon={null}>
              {props.avatarText}
            </UAvatar>
          </div>
        ) : null}
        {props.arrowUp ? (
          <div class={arrowUpPaddingClasses.value} onClick={handlePrependClick}>
            <UIcon size="12" color={arrowColor.value} icon="$arrowUp"></UIcon>
          </div>
        ) : null}
        {slots.default !== undefined && !props.plus ? (
          <div class={labelPaddingClasses.value}>{slots.default?.()}</div>
        ) : null}
        {props.arrowRight ? (
          <div
            class={arrowRightPaddingClasses.value}
            onClick={handleAppendClick}
          >
            <UIcon
              size="12"
              color={arrowColor.value}
              icon="$arrowRight"
            ></UIcon>
          </div>
        ) : null}
        {props.plus ? (
          <div class={plusPaddingClasses.value} onClick={handleAppendClick}>
            <UIcon size="12" color={arrowColor.value} icon="$plus"></UIcon>
          </div>
        ) : null}
      </div>
    )
  },
})
