import { computed, ref } from 'vue'
import { syncExpenseClaimFilesToDraft } from '../../utils/expenseClaimAttachmentSync.js'

export function useTravelReimbursementAttachments({
  isKnowledgeSession,
  reviewFilePreviews,
  linkedRequest,
  draftClaimId,
  activeReviewPayload,
  reviewInlinePendingFiles,
  reviewInlineForm,
  reviewInlineEditorKey,
  composerUploadIntent,
  submitting,
  reviewActionBusy,
  toast,
  fileInputRef,
  createExpenseClaimItem,
  fetchExpenseClaimDetail,
  fetchExpenseClaimItemAttachmentMeta,
  fetchExpenseClaimAttachmentAsset,
  uploadExpenseClaimItemAttachment,
  extractReviewAttachmentNames,
  mergeFilesWithLimit,
  mergeFilePreviews,
  isTemporaryPreviewUrl,
  resolveAttachmentPreviewKind,
  resolveDocumentPreview,
  buildFilePreviews,
  buildFileIdentity,
  MAX_ATTACHMENTS,
  VISIBLE_ATTACHMENT_CHIPS,
  clearInlineReviewFieldError
}) {
  const fileInputMode = ref('composer')
  const attachedFiles = ref([])
  const composerFilesExpanded = ref(false)
  const previewRegistry = []
  const restoredDraftPreviewClaims = new Set()

  const visibleAttachedFiles = computed(() => attachedFiles.value.slice(0, VISIBLE_ATTACHMENT_CHIPS))
  const hiddenAttachedFileCount = computed(() => Math.max(0, attachedFiles.value.length - VISIBLE_ATTACHMENT_CHIPS))

  function rememberFilePreviews(filePreviews) {
    reviewFilePreviews.value = mergeFilePreviews(reviewFilePreviews.value, filePreviews)
  }

  function trackPreviewObjectUrl(url) {
    if (!url || !String(url).startsWith('blob:')) {
      return
    }
    previewRegistry.push(url)
  }

  function buildComposerFilePreviews(files) {
    const filePreviews = buildFilePreviews(files, previewRegistry)
    rememberFilePreviews(filePreviews)
    return filePreviews
  }

  function resolveActiveClaimId() {
    return String(draftClaimId.value || linkedRequest.value?.claimId || '').trim()
  }

  async function buildPersistedAttachmentPreview(metadata) {
    const filename = String(metadata?.file_name || '').trim()
    const kind = resolveAttachmentPreviewKind(metadata)
    const previewPath = String(metadata?.preview_url || '').trim()
    if (!filename || !kind || !previewPath) {
      return null
    }

    const blob = await fetchExpenseClaimAttachmentAsset(previewPath)
    const url = URL.createObjectURL(blob)
    trackPreviewObjectUrl(url)
    return {
      filename,
      kind,
      url
    }
  }

  async function restorePersistedDraftAttachmentPreviews(claimId, options = {}) {
    const normalizedClaimId = String(claimId || '').trim()
    if (!normalizedClaimId || isKnowledgeSession.value) {
      return
    }

    const force = Boolean(options.force)
    if (!force && restoredDraftPreviewClaims.has(normalizedClaimId)) {
      return
    }

    try {
      const claim = await fetchExpenseClaimDetail(normalizedClaimId)
      const items = Array.isArray(claim?.items) ? claim.items : []
      const previews = []

      for (const item of items) {
        const itemId = String(item?.id || '').trim()
        if (!itemId) continue

        let metadata = null
        try {
          metadata = await fetchExpenseClaimItemAttachmentMeta(normalizedClaimId, itemId)
        } catch {
          continue
        }

        const filename = String(metadata?.file_name || '').trim()
        const existingPreview = resolveDocumentPreview(reviewFilePreviews.value, filename)
        if (
          !metadata?.previewable ||
          !filename ||
          (existingPreview?.url && !isTemporaryPreviewUrl(existingPreview.url))
        ) {
          continue
        }

        try {
          const preview = await buildPersistedAttachmentPreview(metadata)
          if (preview) {
            previews.push(preview)
          }
        } catch (error) {
          console.warn('Failed to load persisted attachment preview:', error)
        }
      }

      if (previews.length) {
        rememberFilePreviews(previews)
      }
      restoredDraftPreviewClaims.add(normalizedClaimId)
    } catch (error) {
      console.warn('Failed to restore persisted draft attachment previews:', error)
    }
  }

  async function syncComposerFilesToDraft(claimId, files) {
    const normalizedClaimId = String(claimId || '').trim()
    if (!normalizedClaimId || !Array.isArray(files) || !files.length || isKnowledgeSession.value) {
      return { uploadedCount: 0, skippedCount: Array.isArray(files) ? files.length : 0 }
    }

    const syncResult = await syncExpenseClaimFilesToDraft({
      claimId: normalizedClaimId,
      files,
      fetchExpenseClaimDetail,
      createExpenseClaimItem,
      uploadExpenseClaimItemAttachment
    })
    await restorePersistedDraftAttachmentPreviews(normalizedClaimId, { force: true })
    return syncResult
  }

  function triggerFileUpload(mode = 'composer') {
    if (submitting.value || reviewActionBusy.value) return
    fileInputMode.value = mode
    fileInputRef.value?.click()
  }

  function handleFilesChange(event) {
    const files = Array.from(event.target.files ?? [])

    if (fileInputMode.value === 'inline-review' && activeReviewPayload.value) {
      const existingNames = extractReviewAttachmentNames(activeReviewPayload.value)
      const remainingSlots = Math.max(MAX_ATTACHMENTS - existingNames.length, 0)
      const mergeResult = mergeFilesWithLimit(reviewInlinePendingFiles.value, files, remainingSlots)

      if (!remainingSlots && files.length) {
        toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件，当前票据数量已到上限。`)
      } else if (mergeResult.overflowCount > 0) {
        toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件，新增票据已按上限截断。`)
      }

      reviewInlinePendingFiles.value = mergeResult.files
      const allAttachmentNames = [...existingNames, ...mergeResult.files.map((file) => file.name)]
      reviewInlineForm.value = {
        ...reviewInlineForm.value,
        attachment_names: allAttachmentNames.join('、'),
        attachment_count: allAttachmentNames.length,
        pending_attachment_count: mergeResult.files.length
      }
      clearInlineReviewFieldError('attachments')
      reviewInlineEditorKey.value = ''
    } else {
      if (isKnowledgeSession.value) {
        toast('财务知识问答暂不支持上传附件。')
        fileInputMode.value = 'composer'
        if (fileInputRef.value) {
          fileInputRef.value.value = ''
        }
        return
      }

      const mergeResult = mergeFilesWithLimit(attachedFiles.value, files, MAX_ATTACHMENTS)
      attachedFiles.value = mergeResult.files
      if (fileInputMode.value === 'composer-continue' && files.length) {
        composerUploadIntent.value = 'continue_existing'
      }
      if (mergeResult.overflowCount > 0) {
        toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件，已保留前 ${MAX_ATTACHMENTS} 份。`)
      }
      if (attachedFiles.value.length <= VISIBLE_ATTACHMENT_CHIPS) {
        composerFilesExpanded.value = false
      }
    }

    fileInputMode.value = 'composer'
    if (fileInputRef.value) {
      fileInputRef.value.value = ''
    }
  }

  function toggleAttachedFilesExpanded() {
    composerFilesExpanded.value = !composerFilesExpanded.value
  }

  function removeAttachedFile(targetFile) {
    const fileKey = buildFileIdentity(targetFile)
    attachedFiles.value = attachedFiles.value.filter((file) => buildFileIdentity(file) !== fileKey)
    if (attachedFiles.value.length <= VISIBLE_ATTACHMENT_CHIPS) {
      composerFilesExpanded.value = false
    }
    if (!attachedFiles.value.length) {
      composerUploadIntent.value = ''
    }
  }

  function clearAttachedFiles() {
    attachedFiles.value = []
    composerFilesExpanded.value = false
    composerUploadIntent.value = ''
    if (fileInputRef.value) {
      fileInputRef.value.value = ''
    }
  }

  function stopAttachmentRuntime() {
    for (const url of previewRegistry) {
      URL.revokeObjectURL(url)
    }
    previewRegistry.length = 0
  }

  return {
    fileInputMode,
    attachedFiles,
    composerFilesExpanded,
    visibleAttachedFiles,
    hiddenAttachedFileCount,
    rememberFilePreviews,
    trackPreviewObjectUrl,
    buildComposerFilePreviews,
    resolveActiveClaimId,
    buildPersistedAttachmentPreview,
    restorePersistedDraftAttachmentPreviews,
    syncComposerFilesToDraft,
    triggerFileUpload,
    handleFilesChange,
    toggleAttachedFilesExpanded,
    removeAttachedFile,
    clearAttachedFiles,
    stopAttachmentRuntime
  }
}
