<template>
  <a-spin class="message-box" :class="{ 'is-empty': !renderList.length }" style="display: block" :loading="loading">
    <a-tabs v-model:activeKey="messageType" type="rounded" destroy-on-hide>
      <a-tab-pane v-for="item in tabList" :key="item.key">
        <template #title>
          <span>{{ item.title }}{{ formatUnreadLength(item.key) }}</span>
        </template>
        <a-result v-if="!renderList.length" class="message-empty" status="404">
          <template #subtitle>{{ $t('messageBox.noContent') }}</template>
        </a-result>
        <List
          :render-list="renderList"
          :unread-count="unreadCount"
          @item-click="handleItemClick"
          @resend="handleResend"
          @view-history="openHistory"
        />
      </a-tab-pane>
    </a-tabs>
    <a-drawer v-model:visible="historyVisible" width="760px" title="通知投递历史" :footer="false" unmount-on-close @open="fetchHistory">
      <a-table :columns="historyColumns" :data="historyList" :loading="historyLoading" :pagination="historyPagination" row-key="id" @page-change="onHistoryPageChange">
        <template #status="{ record }">
          <a-tag :color="getDeliveryColor(record.status)">
            {{ getDeliveryLabel(record.status) }}
          </a-tag>
        </template>
        <template #operation="{ record }">
          <a-button v-if="canResendDelivery(record.status)" size="mini" type="text" @click="resendDelivery(record.id)">补发</a-button>
        </template>
      </a-table>
    </a-drawer>
  </a-spin>
</template>

<script lang="ts" setup>
import {
  MessageListType,
  MessageRecord,
  NotificationDeliveryRecord,
  queryMessageList,
  queryNotificationDeliveryHistory,
  resendNotificationDelivery,
  setMessageStatus,
} from '@/api/message'
import useLoading from '@/hooks/loading'
import useNotificationSocket from '@/hooks/useNotificationSocket'
import { Message } from '@arco-design/web-vue'
import { computed, reactive, ref, toRefs, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import List from './list.vue'

interface TabItem {
  key: string
  title: string
  avatar?: string
}
const visibleMessageTypes = ['message']
const { loading, setLoading } = useLoading(true)
const messageType = ref('message')
const { t } = useI18n()
const emit = defineEmits<{
  (event: 'unread-count-change', count: number): void
}>()
const messageData = reactive<{
  renderList: MessageRecord[]
  messageList: MessageRecord[]
}>({
  renderList: [],
  messageList: [],
})
toRefs(messageData)
const historyVisible = ref(false)
const historyLoading = ref(false)
const historyList = ref<NotificationDeliveryRecord[]>([])
const historyPagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
})
const historyColumns = [
  { title: '渠道', dataIndex: 'channel_type', width: 90 },
  { title: '目标', dataIndex: 'target', ellipsis: true, tooltip: true },
  { title: '主题', dataIndex: 'subject', ellipsis: true, tooltip: true },
  { title: '状态', slotName: 'status', width: 90 },
  { title: '次数', dataIndex: 'attempt_count', width: 70 },
  { title: '错误原因', dataIndex: 'last_error', ellipsis: true, tooltip: true },
  { title: '操作', slotName: 'operation', width: 80 },
]
const tabList: TabItem[] = [
  {
    key: 'message',
    title: t('messageBox.tab.title.message'),
  },
]
async function fetchSourceData() {
  setLoading(true)
  try {
    const { data } = await queryMessageList()
    messageData.messageList = data
  } catch (err) {
    // you can report use errorHandler or other
  } finally {
    setLoading(false)
  }
}
const upsertMessageToTop = (message: MessageRecord) => {
  messageData.messageList = [message, ...messageData.messageList.filter((item) => item.id !== message.id)]
}
async function readMessage(data: MessageListType) {
  const ids = data.map((item) => item.id)
  await setMessageStatus({ ids })
  fetchSourceData()
}
const fetchHistory = async () => {
  historyLoading.value = true
  try {
    const res = await queryNotificationDeliveryHistory({
      page: historyPagination.current,
      page_size: historyPagination.pageSize,
    })
    const page = res.details || res.data
    historyList.value = page?.data || []
    historyPagination.total = page?.total || 0
  } catch (err) {
    Message.error('获取投递历史失败')
  } finally {
    historyLoading.value = false
  }
}
const onHistoryPageChange = (page: number) => {
  historyPagination.current = page
  fetchHistory()
}
const openHistory = () => {
  historyVisible.value = true
}
const canResendDelivery = (status: string) => {
  return status === 'failed' || status === 'retry_scheduled'
}
const resendDelivery = async (id: number) => {
  await resendNotificationDelivery(id)
  Message.success('补发请求已提交')
  fetchHistory()
  fetchSourceData()
}
const handleResend = (item: MessageRecord) => {
  resendDelivery(item.id)
}
const getDeliveryLabel = (status: string) => {
  const map: Record<string, string> = {
    pending: '待发送',
    sent: '已发送',
    failed: '失败',
    retry_scheduled: '待重试',
  }
  return map[status] || status
}
const getDeliveryColor = (status: string) => {
  const map: Record<string, string> = {
    pending: 'gray',
    sent: 'green',
    failed: 'red',
    retry_scheduled: 'orange',
  }
  return map[status] || 'gray'
}
const renderList = computed(() => {
  return messageData.messageList.filter((item) => messageType.value === item.type)
})
const totalUnreadCount = computed(() => {
  return messageData.messageList.filter((item) => visibleMessageTypes.includes(item.type) && !item.status).length
})
const unreadCount = computed(() => {
  return renderList.value.filter((item) => !item.status).length
})
const getUnreadList = (type: string) => {
  const list = messageData.messageList.filter((item) => item.type === type && !item.status)
  return list
}
const formatUnreadLength = (type: string) => {
  const list = getUnreadList(type)
  return list.length ? `(${list.length})` : ``
}
const handleItemClick = (items: MessageListType) => {
  if (renderList.value.length) readMessage([...items])
}
watch(totalUnreadCount, (count) => emit('unread-count-change', count), { immediate: true })
fetchSourceData()
useNotificationSocket<MessageRecord>({
  onNotification: upsertMessageToTop,
  onReconnectAfter: fetchSourceData,
})
</script>

<style scoped lang="less">
.message-box {
  width: 400px;
  overflow: hidden;

  :deep(.arco-spin-children) {
    overflow: hidden;
  }

  :deep(.arco-tabs-content) {
    max-height: 360px;
    overflow-x: hidden;
    overflow-y: auto;
  }

  &.is-empty {
    :deep(.arco-tabs-content) {
      max-height: none;
      overflow: hidden;
    }

    :deep(.message-empty) {
      padding: 34px 0 22px;
    }
  }
}

:deep(.arco-popover-popup-content) {
  padding: 0;
}

:deep(.arco-list-item-meta) {
  align-items: flex-start;
}
:deep(.arco-tabs-nav) {
  padding: 14px 0 12px 16px;
  border-bottom: 1px solid var(--color-neutral-3);
}
:deep(.arco-tabs-content) {
  padding-top: 0;
  .arco-result-subtitle {
    color: rgb(var(--gray-6));
  }
}
</style>
