<template>
  <div class="sa-export-wrap" @click="handleExport">
    <slot>
      <ElButton :icon="Download" :loading="loading">
        {{ label }}
      </ElButton>
    </slot>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import { Download } from '@element-plus/icons-vue'
  import { ElMessage, ElMessageBox } from 'element-plus'
  import axios from 'axios'
  import { useUserStore } from '@/store/modules/user'
  import { $t } from '@/locales'

  defineOptions({ name: 'SaExport' })

  const props = withDefaults(
    defineProps<{
      url: string
      params?: Record<string, any>
      fileName?: string
      method?: string
      label?: string
    }>(),
    {
      method: 'post',
      label: '导出',
      fileName: '导出数据.xlsx'
    }
  )

  const emit = defineEmits<{
    success: []
    error: [error: any]
  }>()

  const loading = ref(false)

  const handleExport = async () => {
    if (loading.value) return
    if (!props.url) {
      ElMessage.error($t('uiMsg.exportNotConfigured'))
      return
    }

    let finalFileName = props.fileName

    try {
      const { value } = await ElMessageBox.prompt($t('uiMsg.exportPromptFileName'), $t('uiMsg.titlePrompt'), {
        confirmButtonText: $t('uiMsg.btnOk'),
        cancelButtonText: $t('uiMsg.btnCancel'),
        inputValue: props.fileName,
        inputValidator: (val) => !!val.trim() || $t('uiMsg.exportFileNameRequired')
      })
      finalFileName = value
    } catch {
      // User cancelled
      return
    }

    try {
      loading.value = true
      const { VITE_API_URL } = import.meta.env
      const { accessToken } = useUserStore()

      axios.defaults.baseURL = VITE_API_URL

      const config = {
        method: props.method,
        url: props.url,
        data: props.method.toLowerCase() === 'post' ? props.params : undefined,
        params: props.method.toLowerCase() === 'get' ? props.params : undefined,
        responseType: 'blob' as const,
        headers: {
          Authorization: accessToken ? `Bearer ${accessToken}` : undefined
        }
      }

      const res = await axios(config)

      // Check if response is json (error case)
      if (res.data.type === 'application/json') {
        const reader = new FileReader()
        reader.onload = () => {
          try {
            const result = JSON.parse(reader.result as string)
            ElMessage.error(result.msg || $t('uiMsg.exportFail'))
            emit('error', result)
          } catch (e) {
            ElMessage.error($t('uiMsg.exportFail'))
            emit('error', e)
          }
        }
        reader.readAsText(res.data)
        return
      }

      const blob = new Blob([res.data], { type: 'application/octet-stream' })
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = finalFileName
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      URL.revokeObjectURL(url)

      ElMessage.success($t('uiMsg.exportSuccess'))
      emit('success')
    } catch (error: any) {
      console.error(error)
      ElMessage.error(error.message || $t('uiMsg.exportFail'))
      emit('error', error)
    } finally {
      loading.value = false
    }
  }
</script>

<style scoped>
  .sa-export-wrap {
    display: inline-block;
  }
</style>
