<template>
  <component :is="wrapperTag" v-bind="wrapperAttrs">
    <component :is="dynamicIcon" v-bind="iconAttrs" />
  </component>
</template>

<script setup lang="ts">
import * as feather from 'feather-icons'
import { computed } from 'vue'

import { CustomCpIcons } from '@/constants'

export interface Props {
  size?: number | string
  tag?: string
  type: string
}

const props = withDefaults(defineProps<Props>(), {
  size: 24,
  tag: 'i',
})

const wrapperTag = computed(() => props.tag)
const type = computed(() => props.type)
const size = computed(() => props.size)

// @ts-expect-error cannot use string as index type for CustomCpIcons
const isCustomIcon = computed(() => !!CustomCpIcons[type.value])
// @ts-expect-error cannot use string as index type for feather.icons
const isFeatherIcon = computed(() => !!feather.icons[type.value])

const dynamicIcon = computed(() => {
  if (isFeatherIcon.value && isCustomIcon.value) {
    throw new Error(`Icon type "${type.value}" is defined in both feather icons and CustomCpIcons. Please choose one.`)
  }

  if (isFeatherIcon.value) {
    return 'svg'
  } else if (isCustomIcon.value) {
    // @ts-expect-error cannot use string as index type for CustomCpIcons
    return CustomCpIcons[type.value]
  }

  // Fallback to SVG for any other case
  return 'svg'
})

const wrapperAttrs = computed(() => {
  const attrs: Record<string, unknown> = {
    'data-name': type.value,
    'data-type': type.value,
    class: {
      cpIcon: true,
      [`cpIcon--${type.value as string}`]: type.value,
    },
  }

  if (!isCustomIcon.value) {
    attrs['data-tags'] = dynamicIcon.value.tags
  }

  return attrs
})

const iconAttrs = computed(() => {
  const attrs: Record<string, unknown> = {
    height: size.value,
    width: size.value,
  }

  if (isCustomIcon.value) {
    return {
      ...attrs,
      class: 'cpIcon__content',
    }
  } else {
    // Default to square icon if type is not found
    // @ts-expect-error cannot use string as index type for feather.icons
    const featherIcon = feather.icons[type.value] || feather.icons.square
    return {
      ...featherIcon.attrs,
      ...attrs,
      class: [featherIcon.attrs?.class, 'cpIcon__content'],
      innerHTML: featherIcon.contents || '',
    }
  }
})
</script>

<style lang="scss">
.cpIcon {
  overflow: hidden;
  line-height: 1;

  &,
  &__content {
    display: inline-block;
  }

  &__content {
    width: inherit;
    height: inherit;
    vertical-align: top;
  }
}
</style>
