<template>
  <div>
    <!-- 页面标题 -->
    <MenuTitle title="爬虫管理" subtitle="Spider Manager" />
    <!-- 爬虫管理数据表格 -->
    <div class="table-content">
      <el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
        :cell-style="{ textAlign: 'center' }" :row-style="{ height: '60px' }" v-loading="tableData.length == 0"
        element-loading-background="rgba(48, 65, 86, 0.7)">
        <!-- 表头配置 -->
        <el-table-column property="number" label="序号" type="index" width="80" />
        <el-table-column property="spider" label="爬虫代号" show-overflow-tooltip />
        <el-table-column min-width="100" property="spider_name" label="爬虫名称" show-overflow-tooltip />
        <el-table-column min-width="200" property="spider_info" label="任务描述" show-overflow-tooltip />
        <el-table-column label="操作">
          <template #default="scope">
            <div class="btn-group">
              <el-button link type="primary" plain @click="handleDetails(scope.row)">查看任务</el-button>
              <el-button link type="primary" plain @click="handleEditSateId" v-if="scope.row.editable">编辑</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
        <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
          @pagination="getData" />
      </div>
    </div>

    <!-- ST详情对话框 -->
    <el-dialog style="z-index: 999999" draggable v-model="editDialogVisible" title="指定下载以下卫星" width="550"
      @close="handleDialogClose">
      <div class="No-Content" ref="noContentRef">
        <TransitionGroup enter-active-class="animate__animated animate__slideInRight"
          leave-active-class="animate__animated animate__slideOutRight" enter-from-class="animate__opacity-0"
          leave-to-class="animate__opacity-0">
          <NoItem v-for="(no, index) in sateNoList" :key="index" class="no-item-row" :-no="no.norad_cat_id"
            @add-no="handleSateAdd" @del-no="handleSateDel" :reset-selected="resetSelected"></NoItem>
        </TransitionGroup>
      </div>
      <div class="footer">
        <div class="No">
          <span class="text-white font-bold text-nowrap">NORAD编号：</span>
          <el-input @input="handleNumInput" maxlength="6" placeholder="请输入编号" v-model="curSateNo"></el-input>
        </div>
        <div class="btns">
          <el-button :disabled="curSateNo == ''" plain type="primary" @click="addNoToList">添加</el-button>
          <el-popconfirm title="确定删除选中编号吗？" width="200" style="background-color: pink">
            <template #reference>
              <el-button :disabled="curSelSateNo.length === 0" plain type="danger">删除</el-button>
            </template>
            <template #actions="{ confirm, cancel }">
              <el-button size="small" @click="cancel">取消</el-button>
              <el-button type="danger" size="small" @click="
                (e: MouseEvent) => {
                  confirm(e)
                  delNoList()
                }
              ">
                确定
              </el-button>
            </template>
          </el-popconfirm>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue'
import Pagination from '@/components/pagination/index.vue'
import { useRouter } from 'vue-router'
import { getSpiderList, addSateNo, getSateIdList, deleteSateNoList, addSateNoList } from '@/api/system.ts'
import NoItem from './components/NoItem.vue'
import { ElMessage, type UploadProps, type UploadRawFile } from 'element-plus'
import MenuTitle from '@/components/MenuTitle.vue'

// 路由对象
const router = useRouter()
// 表格数据
const tableData = ref([])
// 分页参数
const pageObj = ref({
  total: 10,
  pageSize: 10,
  pageNo: 1
})
// 跳转到任务详情页面
const handleDetails = (row: any) => {
  // 路由跳转并传递参数进行筛选
  router.push({
    path: '/osTaskInformation/list',
    query: {
      jump: 'yes',
      spiderType: row.spider,
      page: 'spiderManager'
    }
  })
}
// 获取爬虫数据的方法
const getData = async () => {
  const res = await getSpiderList({ scrapydServerId: '1', project: 'spiders' })
  tableData.value = res.data
}
// 详情对话框显示状态
const editDialogVisible = ref(false)

//编号item类型定义
interface noradItem {
  id: number
  norad_cat_id: string
  create_time: string
}
// 当前输入的编号
const sateNoList = ref<noradItem[]>([])
// 当前选中的编号列表
const curSateNo = ref('')
// 当前选中的编号列表
const curSelSateNo = ref<string[]>([])
// 重置选中状态的标志
const resetSelected = ref(false)
// 关闭对话框时的处理函数
const handleDialogClose = () => {
  // 清空已选中的编号
  curSelSateNo.value = []

  // 通知子组件全部取消选中
  resetSelected.value = true

  nextTick(() => {
    resetSelected.value = false
  })
}

//添加选中项到当前列表
const handleSateAdd = (no: string) => {
  if (checkNoLeSix(no)) {
    curSelSateNo.value.push(no)
  }
}

//从当前列表删除选中项
const handleSateDel = (no: string | number) => {
  curSelSateNo.value = curSelSateNo.value.filter((item) => item != no)
}

//添加编号发到后端
const addNoToList = async () => {
  const res = await addSateNo({ norad_id: curSateNo.value })
  if (res.code === 0) {
    ElMessage.success('添加编号成功')
    getSateNoList()
  }
  curSateNo.value = ''
}

//编号文件导入后发送到后端
const fileImptAddNoList = async () => {
  try {
    // 调用添加接口，传递读取的编号列表
    const res = await addSateNoList({ norad_id: textFileNumbers.value })
    if (res.code === 0) {
      ElMessage.success('导入编号成功')
    }
    getSateNoList()
  } catch (error: any) {
    ElMessage.error(error.message)
  }
}

//删除选中编号
const delNoList = async () => {
  try {
    // 调用删除接口，传递选中的编号列表
    const res = await deleteSateNoList({ norad_id: curSelSateNo.value })
    if (res.code === 0) {
      ElMessage.success('删除编号成功')
    }
    resetSelected.value = true
    curSelSateNo.value = []
    nextTick(() => {
      resetSelected.value = false
    })
    getSateNoList()
  } catch (error: any) {
    ElMessage.error(error.message)
  }
}
const noContentRef = ref<HTMLDivElement | null>(null)

//新添加滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    const container = noContentRef.value
    if (container) {
      container.scrollTop = container.scrollHeight - container.clientHeight
    }
  })
}

//检查输入的编号个数不大于6
const checkNoLeSix = (no: number | string): boolean => {
  if (String(no).length > 6) {
    ElMessage.error('编号位数错误，长度不能大于6位')
    return false
  }
  return true
}
// 添加编号后滚动到底部
const handleNumInput = (value: string) => {
  const filtered = value.replace(/\D/g, '')
  curSateNo.value = filtered.slice(0, 6)
}
// 打开编辑对话框的方法
const handleEditSateId = async () => {
  editDialogVisible.value = true
  getSateNoList()
}

//获取编号列表
const getSateNoList = async () => {
  try {
    const res = await getSateIdList()
    if (res.code === 0) {
      sateNoList.value = res.data.list || []
    }
  } catch (error: any) {
    ElMessage.error(error.message)
  }
}

//读取文本文件后存储读取的编号
const textFileNumbers = ref<string[]>([])

//监听导入文件的数组变化
watch(textFileNumbers, (newVal) => {
  if (newVal.length > 0) {
    newVal.forEach((num) => { })
    fileImptAddNoList()
  }
})

//判断上传文件类型
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
  // 检查文件是否存在
  if (!rawFile) {
    ElMessage.error('请选择文件')
    return Promise.reject()
  }
  // 检查文件类型
  const isTxtType = rawFile.type === 'text/plain'
  // 检查文件后缀名
  const fileName = rawFile.name
  const isTxtExt = fileName.lastIndexOf('.') > 0 && fileName.slice(fileName.lastIndexOf('.')).toLowerCase() === '.txt'
  // 如果两种检查都不通过
  if (!isTxtType && !isTxtExt) {
    ElMessage.error('只能上传 .txt 格式的文件！')
    //阻止上传
    return Promise.reject()
  }
  // 校验通过
  return true
}

//处理文件上传
const handleFileChange: UploadProps['onChange'] = (uploadFile) => {
  //清空之前的值
  textFileNumbers.value = []
  //获取原生file对象
  const file = uploadFile.raw
  if (!file || !(file instanceof File)) {
    ElMessage.error('未获取到有效文件')
    return
  }
  //验证文件类型
  if (file.type !== 'text/plain' && !file.name.endsWith('.txt')) {
    ElMessage.error('请上传.txt文件')
  }
  //使用FileReader读取文件内容
  const reader = new FileReader()
  //成功的回调
  reader.onload = (event: ProgressEvent<FileReader>) => {
    const textContent = event.target?.result as string
    if (!textContent) {
      throw new Error('文件内容为空')
    }
    textFileNumbers.value = parseTextToNumbers(textContent).map((item) => String(item))
  }
  //失败的回调
  reader.onerror = () => {
    ElMessage.error('文件导入失败，请检查文件是否损坏或重试')
  }
  //读取文件
  reader.readAsText(file, 'utf-8')
}

//解析文件内容
const parseTextToNumbers = (text: string): number[] => {
  if (!text) return []
  //换行符分割
  const lines = text.split(/\r?\n/)
  //遍历处理
  const numbers = lines
    .map((line) => {
      //去除首尾空格
      const trimmedLine = line.trim()
      if (trimmedLine === '') return null
      const number = Number(trimmedLine)
      if (isNaN(number)) {
        return null
      }
      return number
    })
    .filter((num): num is number => num !== null)

  return numbers
}
// 组件挂载时获取数据
onMounted(() => {
  getData()
})
</script>

<style scoped>
:deep(.el-input__inner) {
  color: black;
}

/* 去除按钮边框 */
.el-button:focus {
  outline: none;
}

.table-content {
  padding: 10px;
  margin-top: 30px;
  background: rgba(255, 255, 255, 0.03);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(78, 237, 255, 0.2);
  box-shadow: 0 0 15px rgba(78, 237, 255, 0.1);
  border-radius: 8px;
  padding: 15px;
}

.title {
  text-align: left;
  font-size: 18px;
  font-weight: 500;
  color: white;
}

.btns {
  display: flex;
}

.low-titme {
  color: #ccc;
  text-align: left;
  margin-left: 20px;
}

.divider {
  margin-top: 15px;
}

.No-Content {
  width: 100%;
  height: 200px;
  background-color: #1d5484;
  border: 4px solid #083b67;
  display: flex;
  padding: 10px;
  box-sizing: border-box;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  overflow-x: hidden;
}

.footer {
  margin-top: 20px;
  display: flex;
  justify-content: space-between;
}

.No {
  display: flex;
  align-items: center;
}

.No-Content::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.No-Content::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.No-Content::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
  box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1);
}

.No-Content::-webkit-scrollbar-thumb:hover {
  background: #999;
}

.No-Content::-webkit-scrollbar-button {
  display: none;
}

.No-Content {
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 #f1f1f1;
}

.btn-group {
  display: flex;
  gap: 8px;
  white-space: nowrap;
  justify-content: center;
}

.btn-group .el-button {
  flex-shrink: 0;
}

:deep .el-input__inner {
  color: white;
}
</style>
