<script setup lang="ts">
import { computed, type Slot } from 'vue'
import { useAttrsWithDefaults } from '../../../composables/useAttrsWithDefaults'
import { useHasSlot } from '../../../composables/useHasSlots'
import FdsIcon from '../../FdsIcon/FdsIcon.vue'
import type { FdsInteractionBlockProps } from './types'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(defineProps<FdsInteractionBlockProps>(), {
  variant: 'list',
  disabled: false,
  icon: undefined,
  interactive: true,
  as: 'router-link',
  dataTestid: undefined,
  heading: undefined,
})

const { id, href, target, rel, download, attrs } = useAttrsWithDefaults(props)

const hasSlot = useHasSlot()
const hasStickerSlot = useHasSlot('sticker')

const emit = defineEmits<{
  (e: 'click', event: Event): void
}>()

const autoId = `fds-block-link-${Math.random().toString(36).slice(2, 9)}`
const blockLinkId = computed(() => id.value ?? autoId)

const isInteractive = computed(() => !props.disabled && props.interactive)
const keyboardTabIndex = computed(() => (isInteractive.value ? 0 : -1))

const innerClasses = computed(() => [
  props.disabled ? 'cursor-not-allowed shadow-none hover:border-transparent active:bg-transparent' : 'cursor-pointer',
  !isInteractive.value && 'cursor-auto',
])

const slotWrapperClasses = computed(() => [
  'flex flex-col sm:flex-row justify-between h-fit gap-y-2 gap-x-4',
  !hasSlot.value && 'justify-end',
])

const headerClasses = computed(() => [
  props.variant === 'list' && !props.icon && 'mb-2',
  !hasSlot.value && 'mb-0!',
  props.icon && 'flex-1',
])

const contentClasses = computed(() => [props.icon ? 'items-start gap-3' : 'flex-col'])
const containerClasses = computed(() => [props.icon && 'flex-1'])
const iconClasses = computed(() => [props.disabled && 'text-gray-700'])
const arrowClasses = computed(() => [props.disabled && 'hidden'])
const headerTextClasses = computed(() => [props.disabled ? 'text-gray-700' : 'text-blue-600'])

function handleClick(event: Event) {
  if (!isInteractive.value) {
    event.preventDefault()
    event.stopPropagation()
    return
  }
  emit('click', event)
}

function handleKeydown(event: KeyboardEvent) {
  if (!isInteractive.value) return

  const isEnter = event.key === 'Enter' || event.code === 'Enter' || event.code === 'NumpadEnter'
  const isSpace = event.key === ' ' || event.key === 'Spacebar'

  // Links (incl. router-link): Enter activates natively; only Space needs a synthetic click.
  if (componentType.value === 'a' || componentType.value === 'router-link') {
    if (isSpace) {
      event.preventDefault()
      handleClick(event)
    }
    return
  }

  if (isEnter || isSpace) {
    event.preventDefault()
    handleClick(event)
  }
}

const componentType = computed(() => {
  // When not interactive (disabled or interactive === false), always render as a button
  if (!isInteractive.value) return 'button'
  if (props.as) return props.as
  return href.value ? 'a' : 'button'
})

const linkAttrs = computed(() => {
  if (!isInteractive.value) return {}
  if (componentType.value === 'a') {
    return {
      href: href.value,
      target: target.value,
      rel: rel.value,
      download: download.value,
    }
  }
  if (componentType.value === 'router-link') return { to: href.value }
  // Auto-detect: if href exists and no 'as' specified, use 'a'
  if (href.value && !props.as) return { href: href.value }
  return {}
})

const componentAttrs = computed(() => ({
  ...linkAttrs.value,
  ...attrs,
}))

defineSlots<{
  default?: Slot
  sticker?: Slot
}>()
</script>

<template>
  <component
    :is="componentType"
    v-bind="componentAttrs"
    :id="blockLinkId"
    class="box-border appearance-none text-left w-full flex items-start bg-white p-[calc(1rem-2px)] mb-3 text-blue-600 shadow-lg shadow-blue-200 rounded-2xl no-underline border-2 border-transparent transition-all duration-200 hover:border-blue-600 hover:border-2 active:border-transparent active:shadow-none active:bg-blue_t-100 focus-visible:border-blue-500 focus-visible:border-dashed focus-visible:outline-0"
    :class="innerClasses"
    :target="componentType === 'a' ? target : undefined"
    :rel="componentType === 'a' ? rel : undefined"
    :download="componentType === 'a' ? download : undefined"
    :disabled="componentType === 'button' ? props.disabled : undefined"
    :aria-disabled="props.disabled"
    :tabindex="keyboardTabIndex"
    :data-testid="dataTestid"
    @click="handleClick"
    @keydown="handleKeydown"
  >
    <div class="flex w-full flex-1" :class="contentClasses">
      <FdsIcon
        v-if="icon"
        :name="icon"
        :size="24"
        class="flex items-center justify-center w-6 h-6 fill-blue-500"
        :class="iconClasses"
      />
      <div
        class="flex flex-col text-gray-700 font-normal text-base leading-6 tracking-normal"
        :class="containerClasses"
      >
        <div class="flex items-center gap-4" :class="headerClasses">
          <h3 class="flex-1 font-heading text-lg tracking-normal m-0 leading-md" :class="headerTextClasses">
            {{ heading }}
          </h3>
        </div>
        <div :class="slotWrapperClasses">
          <div class="mb-0-last-child">
            <slot />
          </div>
          <div v-if="hasStickerSlot" class="flex items-end">
            <slot name="sticker" />
          </div>
        </div>
      </div>
    </div>
    <FdsIcon
      v-if="variant === 'link'"
      name="arrowRight"
      :size="24"
      class="ml-3 fill-blue-500 flex self-center"
      :class="arrowClasses"
    />
  </component>
</template>
