<template>
  <el-scrollbar :noresize="true" ref="scrollContainer" class="bg-gray-50">
    <MessageContent :message="item" v-for="item in list" :key="item.id" />
  </el-scrollbar>

  <el-dialog v-model="dialogVisible" title="Tips" width="90%" align-center center>
    <div class="w-full text-base">{{ tipMessage }}</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="warning" block size="large" @click="handleClose">Close window</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import MessageContent from './MessageContent.vue'
import { onMounted, ref, onUnmounted, nextTick } from 'vue'
import { ActivationState, Client } from '@stomp/stompjs'
import { useRoute } from 'vue-router'
import { useMessageStore, usePendingMessageStore, useUserInfoStore } from '@/stores/message'
import * as AuthUtils from '@/utils/auth'
import type { Message } from '@/types/global'
import NotifyMp3 from '@/assets/audio/notify.mp3'
import { listContentByUser } from '@/api/content'
import { nanoid } from 'nanoid'
import { formatDate } from "@/utils/formatTime";
import { useCache } from '@/hooks/useCache'
import StompWorker from '@/worker/stompWorkers?worker'

const stompWorker = new StompWorker()
stompWorker.postMessage("heartbeat")


const emits = defineEmits(['onSendSuccess', 'addMessage', 'onStatusChange'])
const scrollContainer = ref()
const messageStore = useMessageStore()
const userInfoStore = useUserInfoStore()
const pendingMessageStore = usePendingMessageStore()
const route = useRoute()
const tipMessage = ref('')
const dialogVisible = ref(false)
const stompClient = ref()
const isConnected = ref(false)
const { wsCache } = useCache()
const accessToken = route.query.t
const server = ref((import.meta.env.VITE_BASE_URL + '/websocket/message' + '?t=' + accessToken).replace('http', 'ws'))

// 标记是否已经添加欢迎语
const isWelcome = ref(false)
// 判断用户是否点开了当前的浏览器标签
const isVisible = ref(document.visibilityState === 'visible')
const MESSAGE_RECORD_KEY = 'messageRecord'
const handleVisibilityChange = () => {
  isVisible.value = document.visibilityState === 'visible';
  if (isVisible.value) {
    handlePendingMessage()
  }
}

const audio = new Audio(NotifyMp3)
audio.muted = true
const payAudio = () => {
  if (audio.muted) {
    audio.muted = false
    audio.pause()
    audio.play()
  }
}

const list = ref<Message[]>([])

const addMessage = (msg: Message) => {
  list.value.push(msg)
  scrollToBottom()
}


const welcome = ref('')
const initConnect = async () => {
  const key = route.query.k as string
  if (key) {
    server.value += '&k=' + key
  }
  stompClient.value = new Client({
    brokerURL: server.value,
    reconnectDelay: 5000,
    heartbeatIncoming: 0,
    heartbeatOutgoing: 10000,
  })
  stompClient.value.onConnect = async (frame: any) => {
    list.value = []
    await listContent()
    emits('onStatusChange', true)
    isConnected.value = true
    welcome.value = "It's a pleasure to have you with us today! How may I be of service to you?"
    // 欢迎语
    if (list.value.length <= 0 && !isWelcome.value) {
      addMessage({
        content: welcome.value,
        senderId: 0,
        receiverId: userInfoStore.getUserInfo().id,
        username: userInfoStore.getUserInfo().username,
        type: 1,
        cid: nanoid(),
        isReceived: true,
        status: 3,
        id: new Date().getTime()
      })
      isWelcome.value = true
    }
    emits('onSendSuccess')

    // 接收客服消息
    const subscribeUrl = '/user/queue/reply'
    stompClient.value.subscribe(subscribeUrl, onNewMessage)

    // 这是客服收到了消息
    const confirmUrl = '/user/queue/support/confirm'
    stompClient.value.subscribe(confirmUrl, onSupportConfirmMessage)

    // 这是服务器收到了消息
    const serverConfirmUrl = '/user/queue/server/confirm'
    stompClient.value.subscribe(serverConfirmUrl, onServerConfirmMessage)

    const recallUrl = '/user/queue/recall'
    stompClient.value.subscribe(recallUrl, recallMessage)

    // 订阅服务端的心跳连接
    const heartbeatUrl = '/user/queue/heartbeat'
    stompClient.value.subscribe(heartbeatUrl, (messageOutput: any) => {
      console.log('收到心跳', messageOutput)
    })
  }
  stompClient.value.onStompError = (frame: any) => {
    console.log('on stomp error', frame)
  }

  stompClient.value.onChangeState = (state: ActivationState) => {
    if (state === ActivationState.ACTIVE) {
      isConnected.value = true
    }
    console.log('websocket status = ', state)
  }
  stompClient.value.onWebSocketClose = (error: any) => {
    isConnected.value = false
    console.log('websocket close', error, '断开时间', formatDate(new Date()))
    emits('onStatusChange', false)
  }
  stompClient.value.onWebSocketError = (error: any) => {
    isConnected.value = false
    console.log('websocket error', error, '错误时间', formatDate(new Date))
    emits('onStatusChange', false)
  }
  stompClient.value.activate()
}

const onNewMessage = (messageOutput: any) => {
  const body = JSON.parse(messageOutput.body) as Message
  if (body.type === 99) {
    stompClient.value.disconnect()
    return
  }
  console.log('用户收到了消息', body)
  messageStore.setMessageRecord(body)
  audio.play()
  handleAddMessage(body)
}

// 客服已经收到了客户发送的消息
const onSupportConfirmMessage = (messageOutput: any) => {
  const body = JSON.parse(messageOutput.body) as Message
  console.log('客服已经收到了客服发送的消息', body)
  list.value.forEach(msg => {
    if (msg.cid === body.cid) {
      msg.isRead = true
      msg.id = body.id
      msg.status = body.status
    }
  })

}

// 服务器已经收到客户的消息
const onServerConfirmMessage = (messageOutput: any) => {
  const body = JSON.parse(messageOutput.body) as Message
  console.log('服务器已经收到了客户的消息, 修改发送状态', body)



  let data = list.value.filter(item => item.id == body.id)
  if (data === undefined || data.length === 0) {
    list.value.push(body)
    scrollToBottom()
  }

  let messageOK
  list.value.forEach(msg => {
    if (msg.cid === body.cid) {
      msg.isRead = true
      msg.id = body.id
      msg.status = body.status
    }
  })
  if (userInfoStore.getUserInfo().userType === 99) {
    addMessageToCache(body)
  }
}

const recallMessage = (messageOutput: any) => {
  console.log('客户收到撤回请求', messageOutput)
  const body = JSON.parse(messageOutput.body) as Message
  list.value = list.value.filter(item => item.id !== body.id)
}



const handleAddMessage = (message: Message) => {
  // 判断用户是否在视窗
  if (isVisible.value) {
    debugger
    console.log('用户在当前窗口, 告诉客服消息已读')
    addMessage(message)
    stompClient.value.publish({ destination: '/app/customer/read', body: JSON.stringify({ id: message.id }) })
  } else {
    // 先存到store
    console.log('先存到store, content', message.content)
    pendingMessageStore.setMessageRecord(message)
  }
}

// 当用户切换回标签时，处理store的消息
const handlePendingMessage = () => {
  const messageRecords = pendingMessageStore.getMessageRecord();
  if (messageRecords.length > 0) {
    messageRecords.forEach((message: Message) => {
      console.log('从store取回消息,', message.content)
      addMessage(message)
      stompClient.value.publish({ destination: '/app/customer/read', body: JSON.stringify(message) })
      pendingMessageStore.removeMessageRecord(message)
    })
  }
}


const disconnect = () => {
  if (stompClient.value) {
    stompClient.value.deactivate()
  }
  isConnected.value = false
}

const sendMessage = (message: Message) => {
  if (isConnected.value) {
    // 发送消息
    const userInfo = userInfoStore.getUserInfo()
    console.log("userInfo", userInfo)
    console.log('客户发送消息 ', message)
    const data: Message = {
      content: message.content,
      type: message.type,
      username: userInfo.username,
      senderId: userInfo.id,
      cid: nanoid(),
      isReceived: false,
      status: message.status,
    }
    stompClient.value.publish({ destination: '/app/customer/send', body: JSON.stringify(data) })
    // addMessage(data)
    emits('onSendSuccess')
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    const container = scrollContainer.value.$el.querySelector('.el-scrollbar__wrap')
    container.scrollTop = container.scrollHeight
  })
}

// 查询客户聊天记录
const listContent = async () => {
  const res = await listContentByUser()
  list.value = list.value.concat(res)
  if (list.value.length > 0) {
    list.value.forEach(msg => {
      if (!msg.isRead || msg.status == null || msg.status <= 2) {
        stompClient.value.publish({ destination: '/app/customer/read', body: JSON.stringify({ id: msg.id }) })
        msg.status = 3
      }
    })
  }
}

const handleClose = () => {
  window.close()
}

// stomp心跳，每隔10秒发送一次
stompWorker.onmessage = (event) => {
  if (event.data === 'heartbeat') {
    try {
      stompClient.value.publish({ destination: '/app/customer/heartbeat', body: 'ping' })
    } catch (error) {
      // 重新连接
      initConnect()
    }
  }
}

defineExpose({
  addMessage,
  sendMessage,
  payAudio,
  initConnect,
  scrollToBottom,
})

onMounted(async () => {
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

onUnmounted(() => {
  disconnect()
  document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>
