import { computed, ref } from 'vue'

import {
  fetchExpenseClaimItemAttachmentMeta,
  fetchExpenseClaimItemAttachmentPreview
} from '../../services/reimbursements.js'
import {
  buildAttachmentInsightViewModel,
  buildAttachmentRiskCards
} from './travelRequestDetailInsights.js'

export function useTravelRequestDetailAttachmentPreview({
  request,
  expenseItems,
  expenseAttachmentMeta
}) {
  const attachmentPreviewOpen = ref(false)
  const attachmentPreviewLoading = ref(false)
  const attachmentPreviewError = ref('')
  const attachmentPreviewUrl = ref('')
  const attachmentPreviewName = ref('')
  const attachmentPreviewMediaType = ref('')
  const attachmentPreviewItemId = ref('')

  const attachmentPreviewEntries = computed(() =>
    expenseItems.value
      .filter((item) => canPreviewAttachment(item))
      .map((item, index) => ({
        item,
        itemId: item.id,
        index,
        name: resolveAttachmentDisplayName(item) || `第 ${index + 1} 条附件`,
        metadata: resolveAttachmentMeta(item)
      }))
  )
  const currentAttachmentPreviewIndex = computed(() =>
    attachmentPreviewEntries.value.findIndex((entry) => entry.itemId === attachmentPreviewItemId.value)
  )
  const currentAttachmentPreviewEntry = computed(() => {
    const index = currentAttachmentPreviewIndex.value
    return index >= 0 ? attachmentPreviewEntries.value[index] : null
  })
  const attachmentPreviewIndexLabel = computed(() => {
    const currentIndex = currentAttachmentPreviewIndex.value
    const total = attachmentPreviewEntries.value.length
    return currentIndex >= 0 && total > 0 ? `${currentIndex + 1} / ${total}` : ''
  })
  const canNavigateAttachmentPreview = computed(() => attachmentPreviewEntries.value.length > 1)
  const currentAttachmentPreviewInsight = computed(() => {
    const entry = currentAttachmentPreviewEntry.value
    if (!entry) {
      return null
    }

    return buildAttachmentInsightViewModel(resolveAttachmentMeta(entry.item), entry.item)
  })
  const currentAttachmentPreviewRiskCards = computed(() => {
    const entry = currentAttachmentPreviewEntry.value
    if (!entry) {
      return []
    }

    return buildAttachmentRiskCards({
      expenseItems: [entry.item],
      attachmentMetaByItemId: expenseAttachmentMeta
    })
  })

  function resolveAttachmentMeta(item) {
    return expenseAttachmentMeta[item.id] || null
  }

  async function refreshExpenseAttachmentMeta(itemId) {
    if (!request.value.claimId || !itemId) {
      return null
    }

    const payload = await fetchExpenseClaimItemAttachmentMeta(request.value.claimId, itemId)
    expenseAttachmentMeta[itemId] = payload
    return payload
  }

  function resolveAttachmentDisplayName(item) {
    const metadata = resolveAttachmentMeta(item)
    return String(metadata?.file_name || item.attachmentHint || '').trim()
  }

  function hasStoredAttachmentReference(item) {
    return String(item?.invoiceId || '').includes('/')
  }

  function resolveAttachmentPreviewTitle(item) {
    const fileName = resolveAttachmentDisplayName(item)
    return fileName ? `预览附件：${fileName}` : '预览附件'
  }

  function resolveAttachmentRecognition(item) {
    return buildAttachmentInsightViewModel(resolveAttachmentMeta(item), item)
  }

  function buildAttachmentRiskNotice(attachment) {
    const analysis = attachment?.analysis
    const severity = String(analysis?.severity || '').trim()

    if (!analysis || severity === 'pass') {
      return ''
    }

    const label =
      String(analysis?.label || '').trim()
      || (severity === 'high' ? '高风险' : severity === 'medium' ? '中风险' : '低风险')
    const summary = String(analysis?.summary || analysis?.headline || '').trim() || '附件存在待核对风险。'
    return `${label}：${summary}`
  }

  function canPreviewAttachment(item) {
    if (!item?.invoiceId) {
      return false
    }
    const metadata = resolveAttachmentMeta(item)
    if (metadata) {
      return metadata.previewable !== false
    }
    return true
  }

  function revokeAttachmentPreviewUrl() {
    if (attachmentPreviewUrl.value && attachmentPreviewUrl.value.startsWith('blob:')) {
      URL.revokeObjectURL(attachmentPreviewUrl.value)
    }
    attachmentPreviewUrl.value = ''
  }

  function closeAttachmentPreview() {
    attachmentPreviewOpen.value = false
    attachmentPreviewLoading.value = false
    attachmentPreviewError.value = ''
    attachmentPreviewName.value = ''
    attachmentPreviewMediaType.value = ''
    attachmentPreviewItemId.value = ''
    revokeAttachmentPreviewUrl()
  }

  async function syncExpenseAttachmentMeta() {
    if (!request.value.claimId) {
      return
    }

    const tasks = expenseItems.value
      .filter((item) => item.invoiceId)
      .map(async (item) => {
        try {
          const payload = await fetchExpenseClaimItemAttachmentMeta(request.value.claimId, item.id)
          expenseAttachmentMeta[item.id] = payload
        } catch {
          delete expenseAttachmentMeta[item.id]
        }
      })

    Object.keys(expenseAttachmentMeta).forEach((itemId) => {
      if (!expenseItems.value.some((item) => item.id === itemId && item.invoiceId)) {
        delete expenseAttachmentMeta[itemId]
      }
    })

    await Promise.allSettled(tasks)
  }

  async function loadAttachmentPreview(item) {
    if (!request.value.claimId || !item?.invoiceId) {
      return
    }

    attachmentPreviewLoading.value = true
    attachmentPreviewError.value = ''
    attachmentPreviewItemId.value = item.id
    attachmentPreviewName.value = resolveAttachmentDisplayName(item)
    let metadata = resolveAttachmentMeta(item)

    try {
      if (!metadata) {
        try {
          metadata = await refreshExpenseAttachmentMeta(item.id)
        } catch (error) {
          if (!hasStoredAttachmentReference(item)) {
            throw new Error('当前附件只有文件名记录，原件尚未保存到单据中，请重新上传后预览。')
          }
          throw error
        }
      }
      if (metadata?.previewable === false) {
        throw new Error('当前附件暂不支持直接预览。')
      }
      attachmentPreviewName.value = resolveAttachmentDisplayName(item)
      attachmentPreviewMediaType.value =
        String(metadata?.preview_kind || '').trim() === 'image'
          ? 'image/png'
          : String(metadata?.media_type || '').trim()
      const blob = await fetchExpenseClaimItemAttachmentPreview(request.value.claimId, item.id)
      revokeAttachmentPreviewUrl()
      attachmentPreviewUrl.value = URL.createObjectURL(blob)
      attachmentPreviewMediaType.value = blob.type || attachmentPreviewMediaType.value
    } catch (error) {
      attachmentPreviewError.value = error?.message || '附件预览失败，请稍后重试。'
    } finally {
      attachmentPreviewLoading.value = false
    }
  }

  async function openAttachmentPreview(item) {
    if (!request.value.claimId || !canPreviewAttachment(item)) {
      return
    }

    closeAttachmentPreview()
    attachmentPreviewOpen.value = true
    await loadAttachmentPreview(item)
  }

  async function goToAttachmentPreview(offset) {
    if (!canNavigateAttachmentPreview.value || attachmentPreviewLoading.value) {
      return
    }

    const entries = attachmentPreviewEntries.value
    const currentIndex = currentAttachmentPreviewIndex.value
    const nextIndex = (currentIndex + offset + entries.length) % entries.length
    const nextEntry = entries[nextIndex]
    if (nextEntry?.item) {
      await loadAttachmentPreview(nextEntry.item)
    }
  }

  function goToPreviousAttachmentPreview() {
    void goToAttachmentPreview(-1)
  }

  function goToNextAttachmentPreview() {
    void goToAttachmentPreview(1)
  }

  return {
    attachmentPreviewError,
    attachmentPreviewIndexLabel,
    attachmentPreviewLoading,
    attachmentPreviewMediaType,
    attachmentPreviewName,
    attachmentPreviewOpen,
    attachmentPreviewUrl,
    buildAttachmentRiskNotice,
    canNavigateAttachmentPreview,
    canPreviewAttachment,
    closeAttachmentPreview,
    currentAttachmentPreviewInsight,
    currentAttachmentPreviewRiskCards,
    goToNextAttachmentPreview,
    goToPreviousAttachmentPreview,
    openAttachmentPreview,
    refreshExpenseAttachmentMeta,
    resolveAttachmentDisplayName,
    resolveAttachmentMeta,
    resolveAttachmentPreviewTitle,
    resolveAttachmentRecognition,
    syncExpenseAttachmentMeta
  }
}
