<template>
  <div class="flex radius-base overflow-hidden message-list-modal">
    <div v-show="showCheckUser" class="flex direction-column p-base fill-lighter tree-box">
      <el-input v-model="filterText" placeholder="输入评卷员账号或名称筛选" clearable></el-input>
      <div class="flex-1 m-t-base scroll-y-auto">
        <el-tree
          ref="treeRef"
          show-checkbox
          node-key="id"
          :filter-node-method="filterTree"
          :data="markerTree"
          :props="treeProp"
          @check-change="onCheckChange"
        ></el-tree>
      </div>
    </div>
    <div class="message-info-container">
      <div class="flex direction-column message-info">
        <div class="flex items-center p-base message-info-header">
          <div class="flex flex-1 items-center overflow-hidden send-user">
            <span class="m-r-mini">收件人</span>
            <span class="flex flex-1 overflow-hidden items-center justify-between radius-base m-r-base user-name">
              <span class="flex-1 checked-users"> {{ viewCheckedUser }}</span>
              <el-button class="m-l-base" size="small" type="primary" @click="toggleCheckUser"> 选择收件人 </el-button>
            </span>
          </div>
          <div class="grid pointer m-l-auto close-icon" @click="$emit('close')">
            <el-icon><close /></el-icon>
          </div>
        </div>
        <div class="flex-1 p-base overflow-hidden">
          <div class="full-h radius-base p-base scroll-y-auto message-info-content">
            <content-edit-able
              v-model="messageContent"
              class="full content-edit-able"
              @click="onContentClick"
            ></content-edit-able>
          </div>
        </div>
        <div class="p-base flex items-center justify-end">
          <el-button v-show="showSendPaper" size="small" plain @click="sendCurrentPaper">发送当前试卷</el-button>
          <el-button size="small" type="primary" :disabled="!allowSend" :loading="loading" @click="onSendMessage">
            发送
          </el-button>
        </div>
      </div>
    </div>
  </div>
  <image-preview v-model="previewModalVisible" :url="props.paperPath || ''"></image-preview>
</template>

<script setup lang="tsx" name="MessageSend">
import { ref, computed, watch, nextTick } from 'vue'
import { ElInput, ElButton, ElTree, ElIcon, ElMessage } from 'element-plus'
import { Close } from '@element-plus/icons-vue'
import ContentEditAble from '@/components/common/ContentEditAble.vue'
import ImagePreview from '../ImagePreview.vue'
import useFetch from '@/hooks/useFetch'
import useVModel from '@/hooks/useVModel'

import type { ExtractApiResponse } from '@/api/api'

type MarkerItem = ExtractArrayValue<ExtractApiResponse<'getUserGroup'>['chiffGroup']>
type TreeNode = ExtractArrayValue<ExtractApiResponse<'getUserGroup'>['markerGroup']> & { label: string }

const props = defineProps<{
  replyUserId?: number | null
  paperPath?: string | null
}>()

/** cleat warning */
const emit = defineEmits(['close', 'change-type', 'reply'])

/** 默认的收件人ID */
const replyUserId = useVModel(props, 'replyUserId')

/** 图片预览 */
const previewModalVisible = ref<boolean>(false)

/** 显示收件人tree */
const showCheckUser = ref<boolean>(true)

/** 消息内容 */
const messageContent = ref<string>('')

/** 选中的收件人 */
const checkedUsers = ref<MarkerItem[]>([])

/** 收件人tree 筛选关键字 */
const filterText = ref<string>('')

/** 是否已发送试卷 */
const sendedPaper = ref<boolean>(false)

/** 显示发送试卷按钮 */
const showSendPaper = computed<boolean>(() => {
  return !!props.paperPath && !sendedPaper.value
})

const allowSend = computed<boolean>(() => {
  return !!(messageContent.value && checkedUsers.value.length)
})

const treeRef = ref<InstanceType<typeof ElTree>>()

const viewCheckedUser = computed(() => {
  return checkedUsers?.value?.map((d) => `${d.loginName}-${d.name}`)?.join(';')
})

const toggleCheckUser = () => {
  showCheckUser.value = !showCheckUser.value
}

function isMarker(x: any): x is MarkerItem {
  return !!x.loginName
}

const treeProp = {
  children: 'markers',
  label(treeNode: TreeNode) {
    if (isMarker(treeNode)) {
      return treeNode.name || treeNode.loginName
    }
    return treeNode.label
  },
} as unknown as InstanceType<typeof ElTree>['props']

const filterTree = ((value: string, data: MarkerItem) => {
  if (!value) return true
  return data.name?.includes(value) || data.loginName?.includes(value)
}) as unknown as InstanceType<typeof ElTree>['filterNodeMethod']

watch(filterText, () => {
  treeRef?.value?.filter(filterText.value)
})

const { fetch: getUserGroup, result: userGroup } = useFetch('getUserGroup')

const markerTree = computed<TreeNode[]>(() => {
  if (!userGroup?.value) {
    return []
  }
  const { chiffGroup, deputyGroup, markerGroup } = userGroup.value
  return [
    chiffGroup?.length ? { label: '大组长', markingGroupNumber: -1, markers: chiffGroup } : null,
    deputyGroup?.length ? { label: '小组长', markingGroupNumber: -1, markers: deputyGroup } : null,
    markerGroup?.length
      ? { label: '评卷小组', markers: markerGroup.map((d) => ({ ...d, label: `第${d.markingGroupNumber}组` })) }
      : null,
  ].filter(Boolean) as TreeNode[]
})

watch(
  [replyUserId, markerTree],
  () => {
    nextTick(() => {
      replyUserId.value && markerTree.value.length && treeRef?.value?.setCheckedKeys([replyUserId.value])
    })
  },
  { immediate: true }
)

const onCheckChange = () => {
  checkedUsers.value = (treeRef?.value?.getCheckedNodes(true) as MarkerItem[]) || []
}

watch(messageContent, () => {
  nextTick(() => {
    const paperButton = document.querySelector(`.content-edit-able [data-path="${props.paperPath}"]`)
    sendedPaper.value = !!paperButton
  })
})

const onContentClick = (e: Event) => {
  const target = e.target as HTMLButtonElement
  const path = target.getAttribute('data-path')
  if (path) {
    previewModalVisible.value = true
  }
}

/** 发送当前试卷 */
const sendCurrentPaper = () => {
  if (props.paperPath) {
    messageContent.value += `<span class="pointer inline link-button" contenteditable="false" data-path="${props.paperPath}">查看试卷</span>`
  }
}

const { fetch: sendMessage, loading } = useFetch('sendMessage')

/** 发送消息 */
const onSendMessage = async () => {
  try {
    if (messageContent.value.length > 2000) {
      return ElMessage.error('输入内容过长')
    }
    await sendMessage({
      content: messageContent.value,
      receiveUserIds: checkedUsers.value.map((u) => u.id),
    })
    ElMessage.success('发送成功')
    emit('close')
  } catch (error) {
    console.error(error)
  }
}

getUserGroup()
</script>

<style scoped lang="scss">
.message-list-modal {
  background-color: transparent;
  .tree-box {
    width: 280px;
    height: 446px;
    ::v-deep(.el-tree) {
      min-height: 100%;
    }
  }
  .message-list {
    width: 280px;
    height: 446px;
    background: #fafafa;
    box-shadow: 0px 6px 6px 0px rgba(0, 0, 0, 0.1);
  }
  .message-info-container {
    width: 600px;
    .message-info {
      height: 446px;
      background-color: $color--white;
      .message-info-header {
        border-bottom: $OnePixelLine;
        .send-user {
          font-size: $SmallFont;
          color: $RegularFontColor;
          .user-name {
            min-width: 320px;
            padding: 10px 12px;
            border: $OnePixelLine;
            .checked-users {
              overflow: hidden;
              white-space: nowrap;
            }
          }
        }
        .close-icon {
          width: 20px;
          height: 20px;
          place-items: center;
          font-size: 18px;
          color: $RegularFontColor;
          &:hover {
            color: $NormalColor;
          }
        }
      }
      .message-info-content {
        border: 1px solid $color--primary;
        font-size: $SmallFont;
        ::v-deep(textarea.el-textarea__inner) {
          height: 100%;
        }
      }
    }
  }
}
</style>
