<!-- 任务执行统计卡片组件 -->
<template>
  <div>
    <TableSearch>
      <div class="form-content">
        <div class="ipt">
          <span style="color: white">所属爬虫：</span>
          <el-select
            v-model="searchCondition.spiders"
            placeholder="请选择"
            style="width: 220px"
            :disabled="!taskSelectOptions.length"
          >
            <el-option
              v-for="item in taskSelectOptions || []"
              :key="item?.spider"
              :label="item?.spider || '未知'"
              :value="item?.spider"
            />
          </el-select>
        </div>
        <div class="btns">
          <el-button plain type="primary" @click="search">查询</el-button>
          <el-button @click="resetData" style="margin-right: 20px">重置</el-button>
          <el-button plain type="primary" @click="openTaskDialog">新建任务</el-button>
        </div>
      </div>
    </TableSearch>
    <div class="cardStyle">
      <div v-if="taskList.length === 0 && !isLoading" class="empty-tip">暂无任务数据</div>
      <div
        v-loading="taskList.length == 0"
        element-loading-background="rgba(48, 65, 86, 0.7)"
        class="taskCard p-2"
        v-for="task in taskList || []"
        :key="task?.id || task?.taskId"
      >
        <div class="header">
          <span class="task-name"
            >任务名称: {{ (task?.kwargs?.options && JSON.parse(task.kwargs.options).jobName) || "无名称" }}</span
          >
          <el-divider style="margin-top: 5px"></el-divider>
        </div>
        <div class="btns">
          <el-button plain type="primary" @click="editTask(task)" class="editButton" :disabled="!task?.id"
            >编辑</el-button
          >
          <el-button plain type="danger" @click="deleteTask(task)" class="deleteButton" :disabled="!task?.id"
            >删除</el-button
          >
        </div>
        <div class="info">
          <div class="item">
            <span class="wordStyle">启用/停止: </span>
            <el-switch
              v-model="task.status"
              :active-value="'running'"
              :inactive-value="'paused'"
              @change="(newStatus: any) => changeStatus(task, newStatus)"
              :disabled="!task?.id"
            />
          </div>
          <div class="item">
            <span class="wordStyle">执行频率: </span>
            <span class="wordStyle">{{ parseCronExpression(task?.kwargs?.cron) || "未设置" }} </span>
          </div>
          <div class="item">
            <span class="wordStyle">执行次数: </span>
            <span class="wordStyle">{{ formatExactLargeNum(task?.count || 0) }}</span>
          </div>
        </div>
      </div>
    </div>
    <addTaskDialog
      v-model:dialogVisible="showTaskDialog"
      @confirm="handleEdit"
      :mode="editMode"
      @getTaskList="getData"
      :jobId="jobId"
      :exGap="frequency || []"
      :spiderType="belongSpiderType || ''"
      :options="taskOptions || ''"
    />

    <deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getData" :jobId="jobId" :disabled="!jobId" />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import addTaskDialog from "./addTaskDialog.vue";
import { getSpiderTaskList, resumeSpiderTask, pauseSpiderTask, getTaskCount } from "@/api/spiderTask";
import { DeleteMode } from "@/components/Delete/enum.ts";
import { AddMode } from "./enum";
import deleteDialog from "./deleteDialog.vue";
import { ElMessage } from "element-plus";
import { getSpiderList } from "@/api/system.ts";
import formatExactLargeNum from "@/utils/formatExactLargeNum";
import TableSearch from "@/components/TableSearch.vue";

const props = defineProps({
  spiderType: {
    type: String,
    default: "",
  },
  failTask: {
    type: String,
    default: "",
  },
  unusualTask: {
    type: String,
    default: "",
  },
});

// 所有响应式变量初始化时避免 undefined
const taskSelectOptions = ref<any[]>([]); // 初始化为空数组
const searchCondition = ref({
  spiders: "",
  options: "",
});

const taskName = ref("");
const taskValue = ref("");
const belongSpiderType = ref("");
const router = useRouter();
const frequency = ref([]); // 初始化为空字符串，解决 cron 类型错误
const editMode = ref(AddMode.UPDATE_TASK);
const deleteMode = ref(DeleteMode.SINGLE_DELETE);
const showDeleteDialog = ref(false);
const showTaskDialog = ref(false);
const taskSwitch = ref(false);
const taskOptions = ref("");
const jobId = ref("");
const taskList = ref<any[]>([]);
const isLoading = ref(false); // 新增专门的加载状态变量

// 删除任务的方法
const deleteTask = (task: any) => {
  if (!task?.id) return; // 避免 task 为 undefined
  jobId.value = task.id;
  deleteMode.value = DeleteMode.SINGLE_DELETE;
  showDeleteDialog.value = true;
};

// 编辑任务的方法
const editTask = (task: any) => {
  if (!task?.id) return; // 避免 task 为 undefined
  jobId.value = task.id;
  // 安全处理 JSON 字符串，避免解析失败
  try {
    taskOptions.value = JSON.stringify(task?.kwargs?.options ? JSON.parse(task.kwargs.options) : {});
  } catch (err) {
    taskOptions.value = "{}";
  }
  belongSpiderType.value = task?.kwargs?.spider || "";
  frequency.value = task?.kwargs?.interval || []; // 兜底空字符串
  editMode.value = AddMode.UPDATE_TASK;
  showTaskDialog.value = true;
};

// 启动与停止任务的方法
const changeStatus = async (task: any, newStatus: string) => {
  if (!task?.id) return; // 避免 task 为 undefined
  try {
    if (newStatus === "running") {
      await resumeSpiderTask({ job_id: task.id });
      ElMessage.success("任务已启动");
    } else if (newStatus === "paused") {
      await pauseSpiderTask({ job_id: task.id });
      ElMessage.success("任务已暂停");
    }
  } catch (err) {
    ElMessage.error("状态切换失败");
    console.error(err);
    // 状态回滚，避免界面显示错误
    task.status = newStatus === "running" ? "paused" : "running";
  }
};

const handleEdit = () => {};

// 打开新建任务弹窗
const openTaskDialog = () => {
  editMode.value = AddMode.ADD_TASK;
  frequency.value = [];
  showTaskDialog.value = true;
};

// 获取任务列表的方法
const getData = async () => {
  isLoading.value = true; // 开始加载
  try {
    const res = await getSpiderTaskList({
      spiders: searchCondition.value.spiders ? [searchCondition.value.spiders] : [],
    });
    const resId = await getTaskCount({});
    // 安全处理返回数据，避免 res.data 为 undefined
    const taskData = res?.data || [];
    const countData = resId?.data || {};
    // 遍历赋值时兜底
    taskList.value = taskData.map((item: any) => ({
      ...item,
      count: countData[item?.id] ?? 0, // 执行次数兜底 0
      status: item?.status || "paused", // 状态兜底
      kwargs: item?.kwargs || {}, // kwargs 兜底空对象
    }));
  } catch (err) {
    ElMessage.error("获取任务列表失败");
    console.error(err);
    taskList.value = []; // 错误时置空数组
  } finally {
    isLoading.value = false; // 结束加载
  }
};

// 重置任务列表的方法
const resetData = async () => {
  searchCondition.value.spiders = "";
  isLoading.value = true;
  try {
    const res = await getSpiderTaskList({ spiders: [], options: JSON.stringify({ jobName: taskName.value }) });
    const resId = await getTaskCount({});
    const taskData = res?.data || [];
    const countData = resId?.data || {};
    taskList.value = taskData.map((item: any) => ({
      ...item,
      count: countData[item?.id] ?? 0,
      status: item?.status || "paused",
      kwargs: item?.kwargs || {},
    }));
  } catch (err) {
    ElMessage.error("重置任务列表失败");
    console.error(err);
    taskList.value = [];
  } finally {
    isLoading.value = false;
  }
};

// 搜索任务的方法
const search = async () => {
  if (searchCondition.value.spiders === "") {
    ElMessage.warning("请先选择爬虫");
    return;
  }
  isLoading.value = true;
  try {
    const res = await getSpiderTaskList({
      spiders: [searchCondition.value.spiders],
      options: JSON.stringify({ jobName: taskName.value }),
    });
    const resId = await getTaskCount({});
    const taskData = res?.data || [];
    const countData = resId?.data || {};
    taskList.value = taskData.map((item: any) => ({
      ...item,
      count: countData[item?.id] ?? 0,
      status: item?.status || "paused",
      kwargs: item?.kwargs || {},
    }));
  } catch (err) {
    ElMessage.error("搜索任务失败");
    console.error(err);
    taskList.value = [];
  } finally {
    isLoading.value = false;
  }
};

// 解析cron表达式的方法（修复逻辑错误，避免数组越界）
const parseCronExpression = (cronExpression?: string) => {
  // 兜底：cron表达式不存在时返回默认值
  if (!cronExpression) return "未设置";
  const parts = cronExpression.trim().split(" ");
  // 只处理标准 5/6 位 cron 表达式
  if (parts.length < 5 || parts.length > 6) return "表达式格式错误";

  // 遍历每个字段，找到非 * 的字段（修复数组越界问题）
  for (let i = 0; i < parts.length; i++) {
    const part = parts[i].trim();
    if (part !== "*" && part !== "") {
      // 转换为数字，避免非数字字符导致的错误
      const num = parseInt(part, 10);
      const validNum = isNaN(num) ? 1 : num;

      switch (i) {
        case 0:
          return `每${validNum}秒执行一次`;
        case 1:
          return `每${validNum}分钟执行一次`;
        case 2:
          return `每${validNum}小时执行一次`;
        case 3:
          return `每${validNum}天执行一次`;
        case 4:
          return `每${validNum}月执行一次`;
        case 5:
          return `每${validNum}周执行一次`;
        default:
          return "未知频率";
      }
    }
  }
  // 全是 * 时返回默认
  return "每秒执行一次";
};

// 获取爬虫类型列表
const getSpiderTypeList = async () => {
  try {
    const res = await getSpiderList({ scrapydServerId: "1", project: "spiders" });
    taskSelectOptions.value = res?.data || []; // 兜底空数组
  } catch (err) {
    ElMessage.error("获取爬虫列表失败");
    console.error(err);
    taskSelectOptions.value = [];
  }
};

onMounted(() => {
  if (props.spiderType !== "") {
    searchCondition.value.spiders = props.spiderType;
  }
  getData();
  getSpiderTypeList();
});
</script>

<style lang="scss" scoped>
:deep(.el-form-item__label) {
  color: white;
}
.cardStyle {
  padding: 18px;
  gap: 15px;
  width: auto !important;
  display: flex;
  flex-wrap: wrap; // 修复卡片溢出问题
}

.taskContent {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: start;
  height: 100%;
  gap: 6px;
  padding: 5px 0;
}

.task-name {
  color: #fff !important;
  font-size: 18px;
  font-weight: 500;
}

/* 任务卡片样式 */
.taskCard {
  background-image: url("@/assets/picture/box2.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  font-size: 20px;
  min-width: 300px;
  border-radius: 7px;
}

/* 减小表单的间距 */
.form-item {
  margin-bottom: 3px !important;
}

.taskCard .titleStyle {
  display: flex;
  font-size: 20px;
  color: #ffffff;
}

.task-name {
  color: #ccc;
}

.item {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  margin: 8px 0;
}

.taskCard .wordStyle {
  font-size: 16px;
  color: #ffffff;
}

/* 按钮样式微调 */
.editButton,
.recordButton,
.deleteButton {
  margin: 0 3px !important;
}

/* 工具栏样式 */
.toolbarStyle {
  background-image: url("@/assets/picture/box3.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* 表单样式 */
.formStyle {
  margin-top: 0.5%;
  padding: 2px;
}

/* 空数据提示 */
.empty-tip {
  width: 100%;
  text-align: center;
  color: #fff;
  padding: 50px 0;
}

.header {
  margin-top: 10px;
}

.form-content {
  height: 80px;
  padding: 0 30px;
  justify-content: space-between;
  display: flex;
  align-items: center;
}
</style>
