import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { buildSelectedFileCards } from './workbenchAiComposerModel.js'
import { fetchReceiptFolderAsset } from '../../services/receiptFolder.js'
import {
  inferPreviewKindFromBlob,
  inferPreviewKindFromFile,
  isInlinePreviewUrl,
  isTemporaryPreviewUrl,
  resolveDocumentPreviewAsset
} from '../../utils/documentPreviewAssets.js'

function normalizePreviewText(value) {
  return String(value ?? '').replace(/\s+/g, ' ').trim()
}

function formatFileSize(size) {
  const bytes = Number(size || 0)
  if (!Number.isFinite(bytes) || bytes <= 0) {
    return '-'
  }
  if (bytes < 1024 * 1024) {
    return `${Math.max(1, Math.round(bytes / 1024))} KB`
  }
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`
}

function formatFileTime(timestamp) {
  const value = Number(timestamp || 0)
  if (!Number.isFinite(value) || value <= 0) {
    return '-'
  }
  return new Date(value).toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  })
}

function normalizePreviewField(field = {}) {
  const value = normalizePreviewText(field.value ?? field.text)
  if (!value) {
    return null
  }
  return {
    label: normalizePreviewText(field.label || field.key || field.name) || '识别字段',
    value
  }
}

function resolveSourceKind(sourceUrl, rawFile = {}) {
  const type = normalizePreviewText(rawFile?.type).toLowerCase()
  const name = normalizePreviewText(rawFile?.name).toLowerCase()
  if (!sourceUrl) {
    return 'unsupported'
  }
  if (sourceUrl.startsWith('data:image/') || type.startsWith('image/') || /\.(png|jpe?g|webp|gif|bmp|svg)$/.test(name)) {
    return 'image'
  }
  if (type === 'application/pdf' || /\.pdf$/.test(name)) {
    return 'pdf'
  }
  return 'unsupported'
}

function createObjectUrl(rawFile) {
  if (!rawFile || typeof URL === 'undefined' || typeof URL.createObjectURL !== 'function') {
    return ''
  }
  return URL.createObjectURL(rawFile)
}

export function useWorkbenchAiFilePreview({
  attachmentFlow,
  conversationStarted,
  scrollInlineConversationToBottom,
  selectedFiles
}) {
  const filePreviewState = ref({
    open: false,
    key: '',
    objectUrl: '',
    objectKind: '',
    objectSource: '',
    loading: false
  })
  const selectedFileCards = computed(() => buildSelectedFileCards(
    selectedFiles.value,
    (file) => attachmentFlow.resolveAiModeReceiptRecognitionState(file)
  ).map((card, index) => ({
    ...card,
    ocrState: attachmentFlow.resolveAiModeReceiptRecognitionState(selectedFiles.value[index])
  })))

  function clearFilePreviewObjectUrl() {
    const objectUrl = filePreviewState.value.objectUrl
    if (objectUrl && objectUrl.startsWith('blob:') && typeof URL !== 'undefined') {
      URL.revokeObjectURL(objectUrl)
    }
  }

  function findSelectedFile(fileKey) {
    const index = selectedFileCards.value.findIndex((file) => file.key === fileKey)
    if (index < 0) {
      return null
    }
    return {
      card: selectedFileCards.value[index],
      index,
      rawFile: selectedFiles.value[index]
    }
  }

  function resolveTargetDocument(target) {
    if (!target?.rawFile) {
      return null
    }
    const recognitionState = attachmentFlow.resolveAiModeReceiptRecognitionState(target.rawFile) || target.card.ocrState || null
    return recognitionState?.document || null
  }

  function resolveRemotePreviewAsset(target) {
    const asset = resolveDocumentPreviewAsset(resolveTargetDocument(target))
    if (!asset?.url || isInlinePreviewUrl(asset.url) || isTemporaryPreviewUrl(asset.url)) {
      return null
    }
    return asset
  }

  async function loadRemotePreviewAsset(fileKey) {
    const target = findSelectedFile(fileKey)
    const asset = resolveRemotePreviewAsset(target)
    if (!target?.rawFile || !asset?.url) {
      return
    }

    try {
      const blob = await fetchReceiptFolderAsset(asset.url)
      const objectUrl = createObjectUrl(blob)
      const objectKind = inferPreviewKindFromBlob(blob) || asset.kind
      if (!objectUrl || !['image', 'pdf'].includes(objectKind)) {
        return
      }
      if (!filePreviewState.value.open || filePreviewState.value.key !== fileKey) {
        URL.revokeObjectURL(objectUrl)
        return
      }
      clearFilePreviewObjectUrl()
      filePreviewState.value = {
        ...filePreviewState.value,
        objectUrl,
        objectKind,
        objectSource: asset.source,
        loading: false
      }
    } catch (error) {
      console.warn('AI mode remote attachment preview unavailable:', error)
      if (!filePreviewState.value.open || filePreviewState.value.key !== fileKey) {
        return
      }
      clearFilePreviewObjectUrl()
      filePreviewState.value = {
        ...filePreviewState.value,
        objectUrl: createObjectUrl(target.rawFile),
        objectKind: inferPreviewKindFromFile(target.rawFile),
        objectSource: 'file',
        loading: false
      }
    }
  }

  function openAiModeFilePreview(fileKey) {
    const target = findSelectedFile(fileKey)
    if (!target?.rawFile) {
      return
    }
    clearFilePreviewObjectUrl()
    const remoteAsset = resolveRemotePreviewAsset(target)
    filePreviewState.value = {
      open: true,
      key: fileKey,
      objectUrl: remoteAsset ? '' : createObjectUrl(target.rawFile),
      objectKind: remoteAsset ? '' : inferPreviewKindFromFile(target.rawFile),
      objectSource: remoteAsset ? remoteAsset.source : 'file',
      loading: Boolean(remoteAsset)
    }
    if (remoteAsset) {
      void loadRemotePreviewAsset(fileKey)
    }
  }

  function closeAiModeFilePreview() {
    clearFilePreviewObjectUrl()
    filePreviewState.value = {
      open: false,
      key: '',
      objectUrl: '',
      objectKind: '',
      objectSource: '',
      loading: false
    }
  }

  const activeAiModeFilePreview = computed(() => {
    if (!filePreviewState.value.open || !filePreviewState.value.key) {
      return null
    }
    const target = findSelectedFile(filePreviewState.value.key)
    if (!target) {
      return null
    }
    const rawFile = target.rawFile
    const recognitionState = attachmentFlow.resolveAiModeReceiptRecognitionState(rawFile) || target.card.ocrState || null
    const document = recognitionState?.document || null
    const documentFields = Array.isArray(document?.document_fields) ? document.document_fields : document?.fields || []
    const ocrFields = documentFields.map((field) => normalizePreviewField(field)).filter(Boolean)
    const documentPreviewAsset = resolveDocumentPreviewAsset(document)
    const inlinePreviewAvailable = documentPreviewAsset?.url && isInlinePreviewUrl(documentPreviewAsset.url)
    const sourceUrl = inlinePreviewAvailable
      ? documentPreviewAsset.url
      : filePreviewState.value.objectUrl
    const sourceKind = inlinePreviewAvailable
      ? documentPreviewAsset.kind
      : filePreviewState.value.loading
        ? 'loading'
        : filePreviewState.value.objectKind || resolveSourceKind(sourceUrl, rawFile)
    const documentTypeLabel = normalizePreviewText(
      document?.document_type_label ||
        document?.scene_label ||
        document?.document_type ||
        target.card.typeLabel
    )

    return {
      open: true,
      key: target.card.key,
      name: target.card.name,
      sourceKind,
      sourceUrl,
      documentTypeLabel: documentTypeLabel || '待识别',
      recognitionStatus: recognitionState?.status || 'idle',
      recognitionStatusLabel: recognitionState?.label || '等待智能录入识别',
      recognitionStatusTitle: recognitionState?.title || '',
      fileInfoRows: [
        { label: '文件类型', value: target.card.typeLabel },
        { label: '文件大小', value: formatFileSize(rawFile?.size) },
        { label: '上传时间', value: formatFileTime(rawFile?.lastModified) }
      ],
      ocrFields,
      ocrSummary: normalizePreviewText(document?.summary),
      rawText: normalizePreviewText(document?.text).slice(0, 600)
    }
  })

  watch(selectedFiles, (files, previousFiles = []) => {
    attachmentFlow.primeAiModeReceiptContext(files)
    const fileCountChanged = files.length !== previousFiles.length
    if (conversationStarted.value && fileCountChanged) {
      scrollInlineConversationToBottom({ force: true })
    }
    if (filePreviewState.value.open && !findSelectedFile(filePreviewState.value.key)) {
      closeAiModeFilePreview()
    }
  }, { flush: 'sync' })

  onBeforeUnmount(() => {
    closeAiModeFilePreview()
  })

  return {
    activeAiModeFilePreview,
    closeAiModeFilePreview,
    openAiModeFilePreview,
    selectedFileCards
  }
}
