import { ref } from 'vue'
import {
  buildChatHistoryWindowPayload,
  createChatHistoryRecordNormalizer,
  formatChatHistoryVideoDuration,
  getChatHistoryPreviewLines,
  isChatHistoryRecordItemIncomplete,
  normalizeChatHistoryUrl,
  pickFirstMd5,
  stripWeChatInvisible
} from '~/lib/chat/chat-history'
import { openMessageExternalUrl } from '~/lib/chat/message-links'

export const useChatHistoryWindows = ({
  api,
  apiBase,
  selectedAccount,
  selectedContact,
  openImagePreview,
  openVideoPreview,
  buildVoiceUrl
}) => {
  const floatingWindows = ref([])
  let floatingWindowSeq = 0
  let floatingWindowZ = 70
  const floatingDragState = { id: '', offsetX: 0, offsetY: 0 }

  const clampNumber = (value, min, max) => Math.min(max, Math.max(min, value))
  const normalizeRecordItem = createChatHistoryRecordNormalizer({
    apiBase,
    getSelectedAccount: () => selectedAccount.value,
    getSelectedContact: () => selectedContact.value,
    buildVoiceUrl
  })

  const getFloatingWindowById = (id) => {
    const list = Array.isArray(floatingWindows.value) ? floatingWindows.value : []
    return list.find((item) => String(item?.id || '') === String(id || '')) || null
  }

  const focusFloatingWindow = (id) => {
    const windowItem = getFloatingWindowById(id)
    if (!windowItem) return
    floatingWindowZ += 1
    windowItem.zIndex = floatingWindowZ
  }

  const closeFloatingWindow = (id) => {
    const key = String(id || '')
    floatingWindows.value = (Array.isArray(floatingWindows.value) ? floatingWindows.value : []).filter((item) => String(item?.id || '') !== key)
    if (floatingDragState.id && String(floatingDragState.id) === key) {
      floatingDragState.id = ''
    }
  }

  const closeTopFloatingWindow = () => {
    const list = Array.isArray(floatingWindows.value) ? floatingWindows.value : []
    if (!list.length) return
    const top = [...list].sort((a, b) => Number(b?.zIndex || 0) - Number(a?.zIndex || 0))[0]
    if (top?.id) closeFloatingWindow(top.id)
  }

  const openFloatingWindow = (payload) => {
    if (!process.client || typeof window === 'undefined') return null
    floatingWindowSeq += 1
    floatingWindowZ += 1
    const width = clampNumber(Number(payload?.width || 520), 360, Math.max(360, (window.innerWidth || 1200) - 48))
    const height = clampNumber(Number(payload?.height || 420), 320, Math.max(320, (window.innerHeight || 900) - 48))
    const x = clampNumber(Number(payload?.x || Math.round(((window.innerWidth || width) - width) / 2)), 16, Math.max(16, (window.innerWidth || width) - width - 16))
    const y = clampNumber(Number(payload?.y || Math.round(((window.innerHeight || height) - height) / 2)), 16, Math.max(16, (window.innerHeight || height) - height - 16))

    const windowItem = {
      id: `chat-floating-${floatingWindowSeq}`,
      kind: String(payload?.kind || 'chatHistory'),
      title: String(payload?.title || ''),
      info: payload?.info || { isChatRoom: false },
      records: Array.isArray(payload?.records) ? payload.records : [],
      url: String(payload?.url || ''),
      content: String(payload?.content || ''),
      preview: String(payload?.preview || ''),
      from: String(payload?.from || ''),
      fromAvatar: String(payload?.fromAvatar || ''),
      loading: !!payload?.loading,
      width,
      height,
      x,
      y,
      zIndex: floatingWindowZ
    }
    floatingWindows.value = [...floatingWindows.value, windowItem]
    return windowItem
  }

  const startFloatingWindowDrag = (id, event) => {
    if (!process.client) return
    const windowItem = getFloatingWindowById(id)
    if (!windowItem) return
    focusFloatingWindow(id)
    const point = 'touches' in event ? event.touches?.[0] : event
    floatingDragState.id = id
    floatingDragState.offsetX = Number(point?.clientX || 0) - Number(windowItem.x || 0)
    floatingDragState.offsetY = Number(point?.clientY || 0) - Number(windowItem.y || 0)
  }

  const onFloatingWindowMouseMove = (event) => {
    if (!process.client) return
    if (!floatingDragState.id) return
    const windowItem = getFloatingWindowById(floatingDragState.id)
    if (!windowItem) return
    const point = 'touches' in event ? event.touches?.[0] : event
    const nextX = Number(point?.clientX || 0) - floatingDragState.offsetX
    const nextY = Number(point?.clientY || 0) - floatingDragState.offsetY
    windowItem.x = clampNumber(nextX, 8, Math.max(8, (window.innerWidth || nextX) - windowItem.width - 8))
    windowItem.y = clampNumber(nextY, 8, Math.max(8, (window.innerHeight || nextY) - windowItem.height - 8))
  }

  const onFloatingWindowMouseUp = () => {
    floatingDragState.id = ''
  }

  const chatHistoryModalVisible = ref(false)
  const chatHistoryModalTitle = ref('')
  const chatHistoryModalRecords = ref([])
  const chatHistoryModalInfo = ref({ isChatRoom: false })
  const chatHistoryModalStack = ref([])
  const goBackChatHistoryModal = () => {}
  const closeChatHistoryModal = () => {
    chatHistoryModalVisible.value = false
    chatHistoryModalTitle.value = ''
    chatHistoryModalRecords.value = []
    chatHistoryModalInfo.value = { isChatRoom: false }
    chatHistoryModalStack.value = []
  }

  const onChatHistoryVideoThumbError = (record) => {
    if (!record) return
    const candidates = record._videoThumbCandidates
    if (!Array.isArray(candidates) || candidates.length <= 1) {
      record._videoThumbError = true
      return
    }
    const current = Math.max(0, Number(record._videoThumbCandidateIndex || 0))
    const next = current + 1
    if (next < candidates.length) {
      record._videoThumbCandidateIndex = next
      record.videoThumbUrl = candidates[next]
      return
    }
    record._videoThumbError = true
  }

  const onChatHistoryLinkPreviewError = (record) => {
    if (!record) return
    const candidates = record._linkPreviewCandidates
    if (!Array.isArray(candidates) || candidates.length <= 1) {
      record._linkPreviewError = true
      return
    }
    const current = Math.max(0, Number(record._linkPreviewCandidateIndex || 0))
    const next = current + 1
    if (next < candidates.length) {
      record._linkPreviewCandidateIndex = next
      record.preview = candidates[next]
      record._linkPreviewError = false
      return
    }
    record._linkPreviewError = true
  }

  const onChatHistoryFromAvatarLoad = (record) => {
    try {
      if (record) {
        record._fromAvatarImgOk = true
        record._fromAvatarImgError = false
        record._fromAvatarLast = String(record.fromAvatar || '').trim()
      }
    } catch {}
  }

  const onChatHistoryFromAvatarError = (record) => {
    try {
      if (record) {
        record._fromAvatarImgOk = false
        record._fromAvatarImgError = true
        record._fromAvatarLast = String(record.fromAvatar || '').trim()
      }
    } catch {}
  }

  const onChatHistoryQuoteThumbError = (record) => {
    if (!record || !record.quote) return
    const candidates = record._quoteThumbCandidates
    if (!Array.isArray(candidates) || candidates.length <= 1) {
      record._quoteThumbError = true
      return
    }
    const current = Math.max(0, Number(record._quoteThumbCandidateIndex || 0))
    const next = current + 1
    if (next < candidates.length) {
      record._quoteThumbCandidateIndex = next
      record.quote.thumbUrl = candidates[next]
      return
    }
    record._quoteThumbError = true
  }

  const openChatHistoryQuote = (record) => {
    if (!process.client) return
    const quote = record?.quote
    if (!quote) return
    const kind = String(quote.kind || '')
    const url = String(quote.url || '').trim()
    if (!url) return

    if (kind === 'video') {
      openVideoPreview(url, quote?.thumbUrl)
      return
    }
    if (kind === 'image' || kind === 'emoji') {
      openImagePreview(url)
    }
  }

  const getChatHistoryLinkFromText = (record) => {
    const from = String(record?.from || '').trim()
    if (from) return from
    const url = String(record?.url || '').trim()
    if (!url) return ''
    try { return new URL(url).hostname || '' } catch { return '' }
  }

  const getChatHistoryLinkFromAvatarText = (record) => {
    const text = String(getChatHistoryLinkFromText(record) || '').trim()
    return text ? (Array.from(text)[0] || '') : ''
  }

  const openUrlInBrowser = (url) => {
    void openMessageExternalUrl(url)
  }

  const resolveChatHistoryLinkRecord = async (record) => {
    if (!process.client || !record || !selectedAccount.value) return null
    const serverId = String(record?.fromnewmsgid || '').trim()
    if (!serverId || record._linkResolving) return null

    record._linkResolving = true
    try {
      const response = await api.resolveAppMsg({
        account: selectedAccount.value,
        server_id: serverId
      })
      if (response && typeof response === 'object') {
        const title = String(response.title || '').trim()
        const content = String(response.content || '').trim()
        const url = String(response.url || '').trim()
        const from = String(response.from || '').trim()

        const normalizePreviewUrl = (value) => {
          const raw = String(value || '').trim()
          if (!raw) return ''
          if (/^\/api\/chat\/media\//i.test(raw) || /^blob:/i.test(raw) || /^data:/i.test(raw)) return raw
          if (!/^https?:\/\//i.test(raw)) return ''
          try {
            const host = new URL(raw).hostname.toLowerCase()
            if (host.endsWith('.qpic.cn') || host.endsWith('.qlogo.cn')) {
              return `${apiBase}/chat/media/proxy_image?url=${encodeURIComponent(raw)}`
            }
          } catch {}
          return raw
        }

        if (title) record.title = title
        if (content && !stripWeChatInvisible(record.content)) record.content = content
        if (url) record.url = url
        if (from) record.from = from
        if (response.linkStyle) record.linkStyle = String(response.linkStyle || '').trim()
        if (response.linkType) record.linkType = String(response.linkType || '').trim()

        const fromUsername = String(response.fromUsername || '').trim()
        if (fromUsername) record.fromUsername = fromUsername
        const fromAvatarUrl = fromUsername
          ? `${apiBase}/chat/avatar?account=${encodeURIComponent(selectedAccount.value || '')}&username=${encodeURIComponent(fromUsername)}`
          : (url ? `${apiBase}/chat/media/favicon?url=${encodeURIComponent(url)}` : '')
        if (fromAvatarUrl) {
          const last = String(record._fromAvatarLast || '').trim()
          record.fromAvatar = fromAvatarUrl
          if (String(fromAvatarUrl).trim() !== last) {
            record._fromAvatarLast = String(fromAvatarUrl).trim()
            record._fromAvatarImgOk = false
            record._fromAvatarImgError = false
          }
        }

        const style = String(response.linkStyle || '').trim()
        const thumb = String(response.thumbUrl || '').trim()
        const cover = String(response.coverUrl || '').trim()
        const picked = style === 'cover' ? (cover || thumb) : (thumb || cover)
        const previewResolved = normalizePreviewUrl(picked)
        if (previewResolved) {
          const currentPreview = String(record.preview || '').trim()
          const candidates = Array.isArray(record._linkPreviewCandidates) ? record._linkPreviewCandidates.slice() : []
          if (currentPreview && !candidates.includes(currentPreview)) candidates.push(currentPreview)
          if (!candidates.includes(previewResolved)) candidates.push(previewResolved)
          record._linkPreviewCandidates = candidates
          if (!currentPreview || record._linkPreviewError) {
            record.preview = previewResolved
            record._linkPreviewCandidateIndex = candidates.indexOf(previewResolved)
            record._linkPreviewError = false
          }
        }
        return response
      }
    } catch {}
    finally {
      try { record._linkResolving = false } catch {}
    }
    return null
  }

  const resolveChatHistoryLinkRecords = (windowItem) => {
    if (!process.client) return
    const records = Array.isArray(windowItem?.records) ? windowItem.records : []
    const targets = records.filter((record) => {
      if (!record) return false
      if (String(record.renderType || '') !== 'link') return false
      if (!String(record.fromnewmsgid || '').trim()) return false
      const fromMissing = String(record.from || '').trim() === ''
      const previewMissing = !String(record.preview || '').trim()
      const urlMissing = !String(record.url || '').trim()
      const fromAvatarMissing = !String(record.fromAvatar || '').trim()
      return fromMissing || previewMissing || urlMissing || fromAvatarMissing
    })
    if (!targets.length) return
    ;(async () => {
      for (const target of targets.slice(0, 12)) {
        await resolveChatHistoryLinkRecord(target)
      }
    })()
  }

  const openChatHistoryLinkWindow = (record) => {
    if (!process.client) return
    const title = String(record?.title || record?.content || '链接').trim()
    const url = String(record?.url || '').trim()
    const preview = String(record?.preview || '').trim()
    const from = String(record?.from || '').trim()
    const fromAvatar = String(record?.fromAvatar || '').trim()
    const needResolve = !!String(record?.fromnewmsgid || '').trim() && (!url || !from || !preview || !fromAvatar)
    const windowItem = openFloatingWindow({
      kind: 'link',
      title: title || '链接',
      url,
      content: String(record?.content || '').trim(),
      preview,
      from,
      fromAvatar,
      width: 520,
      height: 420,
      loading: needResolve
    })
    if (!windowItem) return
    focusFloatingWindow(windowItem.id)
    try {
      windowItem._linkPreviewCandidates = Array.isArray(record?._linkPreviewCandidates) ? record._linkPreviewCandidates.slice() : (preview ? [preview] : [])
      windowItem._linkPreviewCandidateIndex = Math.max(0, Number(record?._linkPreviewCandidateIndex || 0))
      windowItem._linkPreviewError = false
      windowItem._fromAvatarLast = fromAvatar
      windowItem._fromAvatarImgOk = !!record?._fromAvatarImgOk
      windowItem._fromAvatarImgError = !!record?._fromAvatarImgError
      windowItem.fromnewmsgid = String(record?.fromnewmsgid || '').trim()
    } catch {}
    if (needResolve) {
      ;(async () => {
        await resolveChatHistoryLinkRecord(windowItem)
        windowItem.loading = false
      })()
    }
  }

  const openChatHistoryModal = (message) => {
    if (!process.client) return
    const { title0, info0, records0 } = buildChatHistoryWindowPayload(message, normalizeRecordItem)
    const windowItem = openFloatingWindow({
      kind: 'chatHistory',
      title: title0 || '聊天记录',
      info: info0,
      records: records0,
      width: 560,
      height: Math.round(Math.max(420, (window.innerHeight || 700) * 0.78))
    })
    if (!windowItem) return
    try { resolveChatHistoryLinkRecords(windowItem) } catch {}
  }

  const openNestedChatHistory = (record) => {
    if (!process.client) return
    const title = String(record?.title || '聊天记录')
    const content = String(record?.content || '')
    const recordItem = String(record?.recordItem || '').trim()
    const serverId = String(record?.fromnewmsgid || '').trim()
    const recordIndexPrefix = String(record?.recordIndexPath || record?._recordIndexPath || '').trim()
      || (Number.isFinite(Number(record?.recordIndex)) ? String(Number(record.recordIndex)) : '')

    const { info0, records0 } = buildChatHistoryWindowPayload({
      title,
      content,
      recordItem,
      recordAttachKey: record?.recordAttachKey || record?._recordAttachKey || '',
      recordIndexPrefix
    }, normalizeRecordItem)
    const windowItem = openFloatingWindow({
      kind: 'chatHistory',
      title: title || '聊天记录',
      info: info0,
      records: records0,
      width: 560,
      height: Math.round(Math.max(420, (window.innerHeight || 700) * 0.78)),
      loading: false
    })
    if (!windowItem) return
    try { resolveChatHistoryLinkRecords(windowItem) } catch {}

    if (!serverId || !selectedAccount.value || record?._nestedResolving || !isChatHistoryRecordItemIncomplete(recordItem)) return
    record._nestedResolving = true
    windowItem.loading = true

    ;(async () => {
      try {
        const response = await api.resolveNestedChatHistory({
          account: selectedAccount.value,
          server_id: serverId
        })
        const resolved = String(response?.recordItem || '').trim()
        if (!resolved) return
        windowItem.title = String(response?.title || title || '聊天记录')
        const { info0: resolvedInfo, records0: resolvedRecords } = buildChatHistoryWindowPayload({
          title: response?.title || title,
          content: response?.content || content,
          recordItem: resolved,
          recordAttachKey: record?.recordAttachKey || record?._recordAttachKey || '',
          recordIndexPrefix
        }, normalizeRecordItem)
        windowItem.info = resolvedInfo || { isChatRoom: false, count: 0 }
        windowItem.records = Array.isArray(resolvedRecords) ? resolvedRecords : []
        if (!windowItem.records.length) {
          const lines = String(response?.content || content || '').trim().split(/\r?\n/).map((item) => item.trim()).filter(Boolean)
          windowItem.info = { isChatRoom: false, count: 0 }
          windowItem.records = lines.map((line, idx) => normalizeRecordItem({
            id: String(idx),
            recordIndex: idx,
            datatype: '1',
            sourcename: '',
            sourcetime: '',
            content: line,
            renderType: 'text'
          }))
        }
        try { resolveChatHistoryLinkRecords(windowItem) } catch {}
      } catch {}
      finally {
        windowItem.loading = false
        try { record._nestedResolving = false } catch {}
      }
    })()
  }

  return {
    floatingWindows,
    chatHistoryModalVisible,
    chatHistoryModalTitle,
    chatHistoryModalRecords,
    chatHistoryModalInfo,
    chatHistoryModalStack,
    goBackChatHistoryModal,
    closeChatHistoryModal,
    getFloatingWindowById,
    focusFloatingWindow,
    closeFloatingWindow,
    closeTopFloatingWindow,
    openFloatingWindow,
    startFloatingWindowDrag,
    onFloatingWindowMouseMove,
    onFloatingWindowMouseUp,
    formatChatHistoryVideoDuration,
    getChatHistoryPreviewLines,
    onChatHistoryVideoThumbError,
    onChatHistoryLinkPreviewError,
    onChatHistoryFromAvatarLoad,
    onChatHistoryFromAvatarError,
    onChatHistoryQuoteThumbError,
    openChatHistoryQuote,
    getChatHistoryLinkFromText,
    getChatHistoryLinkFromAvatarText,
    openUrlInBrowser,
    resolveChatHistoryLinkRecord,
    resolveChatHistoryLinkRecords,
    openChatHistoryLinkWindow,
    openChatHistoryModal,
    openNestedChatHistory
  }
}
