<script setup lang="ts">
import { computed } from 'vue'
import { useAttrsWithDefaults } from '../../../composables/useAttrsWithDefaults'
import { useDownload } from '../../../composables/useDownload'
import FdsIcon from '../../FdsIcon/FdsIcon.vue'
import type { FdsButtonDownloadProps } from './types'

const props = withDefaults(defineProps<FdsButtonDownloadProps>(), {
  loading: false,
  iconPos: 'left',
  href: undefined,
  downloadOptions: undefined,
  text: '',
  disabled: false,
  dataTestid: undefined,
})

const { disabled, attrs } = useAttrsWithDefaults(props)

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

const { downloadFile, isDownloading } = useDownload()

const elBase = computed(() => [
  'inline-block transition-opacity duration-200 text-left',
  'box-border appearance-none inline-flex items-center justify-center shadow-none p-0.5 text-base',
  'select-none m-0 rounded-md align-middle whitespace-nowrap no-underline',
  'transition-[box-shadow,border-color,background-color] duration-200 font-main text-base',
  'leading-5 tracking-normal',
  disabled.value && 'text-gray-500 cursor-not-allowed!',
])

const stateClasses = computed(() => [
  'focus-visible:outline-dashed focus-visible:outline-2 focus-visible:outline-offset-4',
  'focus-visible:outline-blue-500 hover:bg-blue_t-100 active:bg-blue_t-200',
])

const iconOrderClasses = computed(() => (props.iconPos === 'right' ? 'order-2 ml-2 mr-0' : 'mr-2'))

const buttonClasses = computed(() => [
  elBase.value,
  stateClasses.value,
  'border-0 font-normal bg-transparent',
  isDownloading.value ? 'cursor-not-allowed text-gray-500' : 'cursor-pointer text-blue-600',
])

const iconFillClass = computed(() => (isDownloading.value || disabled.value ? 'fill-gray-500' : 'fill-blue-500'))

const handleDownload = async (ev: MouseEvent) => {
  if (disabled.value || props.loading || isDownloading.value) {
    ev.preventDefault()
    return
  }

  // If no downloadOptions, just emit click and let default link behavior handle it
  if (!props.downloadOptions || !props.href) {
    emit('click', ev)
    return
  }

  ev.preventDefault()

  const options = props.downloadOptions
  const headers: Record<string, string> = {}
  headers[options.headerAuthKey || 'Authorization'] = `${options.headerAuthValuePrefix || 'Bearer '}${options.token}`

  if (options.accept) {
    headers.Accept = options.accept
  }

  try {
    const url = props.href
    const filename = undefined // Extract from Content-Disposition header
    const token = undefined // Use custom headers instead
    await downloadFile(url, filename, token, headers)

    if (options.onFinishCallback) {
      options.onFinishCallback()
    }
  } catch (error) {
    if (options.errorHandler) {
      options.errorHandler(error)
    } else {
      throw error
    }
  }
}

const onClick = (ev: MouseEvent) => {
  if (props.downloadOptions) {
    handleDownload(ev)
  } else {
    if (disabled.value || props.loading) {
      ev.preventDefault()
      return
    }
    emit('click', ev)
  }
}

const buttonAttrs = computed(() => {
  const result: Record<string, unknown> = {
    ...attrs,
  }
  if (props.dataTestid) {
    result['data-testid'] = props.dataTestid
  }
  return result as any
})
</script>

<template>
  <button
    v-bind="buttonAttrs"
    :class="buttonClasses"
    :disabled="disabled || loading || isDownloading"
    type="button"
    @click="onClick"
    :aria-disabled="disabled ? 'true' : undefined"
  >
    <span :class="iconOrderClasses" aria-hidden="true">
      <FdsIcon :class="iconFillClass" name="download" :size="24" />
    </span>
    {{ text }}
  </button>
</template>
