let task_list = []
let cur_task = null //当前选择的task--用于修改缓存时使用
let cur_task_id = 0 //当前选择的cur_task_id
let ws = null

// 页面卸载时断开连接
window.addEventListener("beforeunload", function() {
  if (ws) {
    ws.close();
    ws =null;
  }
  task_list = []
  cur_task = null;
  cur_task_id = 0;
});

// 页面加载完成后调用接口获取任务列表数据
document.addEventListener("DOMContentLoaded", async () => {
    //建立wbsocket
    initWebSocket()
    //获取左侧任务列表
    getTasklist();
    //当前选中的数据要清空
    cur_task = null;
    cur_task_id = 0;
    //任务基本信息界面初始化
    document.getElementById("detailTestTarget").textContent = "-";
    document.getElementById("detailTestStatus").textContent = "-";
    document.getElementById("detailSafeStatus").textContent = '-';
    //单选按钮
    set_radio_selection('testMode', 'auto');
    setSetpBtnStatus();
    //节点树界面初始化
    update_select_node_data_show("-","-","-","-","-","-",false)
    //单选按钮点击事件 ------ 是不是更规范的编程方式,应该把控件事件的添加都放页面加载完成后处理
    const autoRadio = document.getElementById("autoMode");
    const manualRadio = document.getElementById("manualMode");
    autoRadio.addEventListener("click", () => updateTestMode(1));
    manualRadio.addEventListener("click", () => updateTestMode(0));
    //tab页点击刷新数据
    document.getElementById("testInstructionsTab").addEventListener("click",()=>searchInstructions());
    document.getElementById("vulnerabilitiesTab").addEventListener("click",()=>searchVulnerabilities());
    //指令和漏洞数据的导出按钮点击事件
    document.getElementById("instrExportBtn").addEventListener("click",()=>ExportInstructions());
    document.getElementById("vulExportBtn").addEventListener("click",()=>ExportVuls());


});

//----------------------左侧任务列表-----------------------
function getstrsafeR(safeRank){
  if(safeRank === 0){
    safeR = "安全";
  }
  else{
    safeR = "存在风险";
  }
  return safeR;
}
function getstrTaskS(taskStatus){
  if(taskStatus === 0){
    taskS = "暂停中";
  }else if(taskStatus === 1){
    taskS = "执行中";
  }else {
    taskS = "已完成";
  }
  return taskS;
}

async function getTasklist(){
    try {
      const res = await fetch("/api/task/getlist");
      if (!res.ok) {
        const errorData = await res.json();
        throw new Error(errorData.error || `HTTP错误 ${res.status}`);
      }
      const data = await res.json();
      task_list = data.tasks
      updateTasklistShow()
    } catch (error) {
      console.error("加载任务列表出错:", error);
      document.getElementById("taskList").innerHTML = "<p>加载任务列表失败!</p>";
    }
}
function updateTasklistShow(){
  const taskList = document.getElementById("taskList");
      taskList.innerHTML = ""; // 清空“加载中”提示
      // 遍历任务数组,生成任务项
      task_list.forEach((task) => {
        const taskItem = document.createElement("div");
        taskItem.dataset.taskID =task.taskID //在taskItem添加数据属性,这是关联数据的第二种方法,selectedEl.dataset.taskId; 感觉比cur_task更好
        taskItem.className = "task-item";

        // 第一行:测试目标
        const targetDiv = document.createElement("div");
        targetDiv.className = "task-target";
        targetDiv.textContent = task.testTarget;
        taskItem.title = task.testTarget; // 加上鼠标悬浮提示
        taskItem.appendChild(targetDiv);

        // 第二行:测试状态,带缩进
        const statusDiv = document.createElement("div");
        statusDiv.className = "task-status";
        let safeR = getstrsafeR(task.safeRank);
        let taskS = getstrTaskS(task.taskStatus);
        if (taskS === "执行中") {
          taskItem.classList.add("running");
        }
        statusDiv.textContent = `${taskS}-${safeR}`;
        taskItem.appendChild(statusDiv);

        // 可绑定点击事件:点击任务项更新右侧详情
        taskItem.addEventListener("click", () => {
          // 取消所有任务项的选中状态
          document.querySelectorAll(".task-item.selected").forEach(item => {
            item.classList.remove("selected");
          });
          // 给当前点击的任务项添加选中状态
          taskItem.classList.add("selected");
          //执行业务代码 --参数当前选中task的数据
          cur_task = task;
          selected_task_item()
        });
        taskList.appendChild(taskItem);
      });
}

//选中tasklist--更新界面数据
function selected_task_item(){
  if(cur_task_id === cur_task.taskID) return;
  cur_task_id = cur_task.taskID;
  //按钮状态更新
  actionButton = document.getElementById("actionButton");
  if(cur_task.taskStatus === 0){
    actionButton.textContent = "启动";
  }else if(cur_task.taskStatus === 1){
    actionButton.textContent = "暂停";
  }else {
  }
  //基本信息
  let safeR = getstrsafeR(cur_task.safeRank);
  let taskS = getstrTaskS(cur_task.taskStatus);
  document.getElementById("detailTestTarget").textContent = cur_task.testTarget;
  document.getElementById("detailTestStatus").textContent = taskS;
  document.getElementById("detailSafeStatus").textContent = safeR;
  //单选按钮
  if(cur_task.workType === 0){ //人工
    set_radio_selection('testMode', 'manual');
  }else { //1-自动
    set_radio_selection('testMode', 'auto');
  }
  //更新单步按钮
  setSetpBtnStatus()
  //加载任务其他信息--node_tree.js
  loadNodeTree(cur_task_id);
  //加载测试指令和漏洞数据
  searchInstructions();
  searchVulnerabilities();
  // renderTableRows(document.querySelector("#instrTable tbody"), []);
  // renderTableRows(document.querySelector("#vulTable tbody"), []);
}

//--------------------任务基本信息区域--------------------
//单选按钮--测试模式修改
async function updateTestMode(mode){ //0-人工,1-自动
  if(cur_task){
    if(cur_task.workType !== mode){
      if(cur_task.taskStatus === 1){
        alert("执行状态,不允许修改测试模式!");
        if( cur_task.workType === 0){ //人工
          set_radio_selection('testMode', 'manual');
        }else { //1-自动
          set_radio_selection('testMode', 'auto');
        }
      }
      else {//不是执行状态,可以修改测试模式
          try {
            const res = await fetch("/api/task/taskworktype", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ cur_task_id,mode }),      //task_id:task_id
            });
            // 新增状态码校验
            if (!res.ok) {
              const errorData = await res.json();
              throw new Error(errorData.error || `HTTP错误 ${res.status}`);
            }
            const data = await res.json();
            bsuccess = data.bsuccess;
            if(bsuccess){
              cur_task.workType = mode; //更新前端缓存
              //更新单步按钮状态
              setSetpBtnStatus()
            }else {
              alert("修改测试模失败!")
              if( cur_task.workType === 0){ //人工  修改失败还原单选按钮点击状态
                set_radio_selection('testMode', 'manual');
              }else { //1-自动
                set_radio_selection('testMode', 'auto');
              }
            }
          } catch (error) {
            console.error("控制任务状态异常:", error);
            alert("控制任务状态异常:"+error);
            if( cur_task.workType === 0){ //人工  修改失败还原单选按钮点击状态
              set_radio_selection('testMode', 'manual');
            }else { //1-自动
              set_radio_selection('testMode', 'auto');
            }
          }
      }
    }
  }


}

//点击暂停/继续按钮
document.getElementById("actionButton").addEventListener("click",() => {
  controlTask();
});
async function controlTask(){
  if(cur_task_id === 0){
    alert("请先选择一个任务!")
    return
  }
  if(cur_task.taskStatus === 1){
    if (!confirm("确认暂停该任务吗?为保障任务执行,暂停后需要等待工作线程都执行完当前任务并退出后,才可以重新启动! ")){
      return
    }
  }

  try {
    const res = await fetch("/api/task/taskcontrol", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ cur_task_id }),      //task_id:task_id
    });
    if (!res.ok) {
      const errorData = await res.json();
      throw new Error(errorData.error || `HTTP错误 ${res.status}`);
    }
    const data = await res.json();
    newstatus = data.newstatus;
    //更新页面
    if(newstatus === 0){
      document.getElementById("detailTestStatus").textContent = "暂停中";
      actionButton.textContent = "启动";
    }else if(newstatus === 1){
      document.getElementById("detailTestStatus").textContent = "执行中";
      actionButton.textContent = "暂停";
    }else {
      document.getElementById("detailTestStatus").textContent = "已完成";
      actionButton.textContent = "已完成";
    }
    cur_task.taskStatus = newstatus;  //光有个cur_taks也可以
    setSetpBtnStatus();
    //更新task_list的显示
    updateTaskList();
    alert("控制任务状态成功!")
  } catch (error) {
    console.error("控制任务状态异常:"+error);
    alert("控制任务状态异常:"+error);
  }
}

//结束任务-brun-false
document.getElementById("btnTaskOver").addEventListener("click",()=>{
  overTask();
})
async function overTask(){
  if(cur_task_id === 0){
    alert("请先选择一个任务!")
    return
  }
   try {
    if (confirm('确定要结束此任务吗?')){
       const res = await fetch("/api/task/taskover", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ cur_task_id }),      //task_id:task_id
    });
      // 新增状态码校验
      if (!res.ok) {
        const errorData = await res.json();
        throw new Error(errorData.error || `HTTP错误 ${res.status}`);
      }
      const data = await res.json();
      bsuccess = data.bsuccess;
      error = data.error;
      if(bsuccess){
        //更新页面
        task_list = []
        cur_task = null //当前选择的task--用于修改缓存时使用
        cur_task_id = 0 //当前选择的cur_task_id
        //重新获取任务list
        getTasklist();
      }else {
        alert("结束任务失败:"+error);
      }
    }
  } catch (error) {
    alert("结束任务失败:"+error);
  }
}

//修改了涉及到tasklist的展示内容,修改tasklist显示
function updateTaskList(){
  //更新数据
  const selectedEl = document.querySelector(".task-item.selected");
  if (selectedEl) {
    let safeR = getstrsafeR(cur_task.safeRank);
    let taskS = getstrTaskS(cur_task.taskStatus);
    if (taskS === "执行中") {
      selectedEl.classList.add("running");
    } else {
      selectedEl.classList.remove("running");
    }
    const statusDiv = selectedEl.querySelector(".task-status");
    statusDiv.textContent = `${taskS}-${safeR}`;
  }
}

//设置单步按钮的可点击状态状态
function setSetpBtnStatus(){
  if(cur_task){
    task_status = cur_task.taskStatus;
    work_type = cur_task.workType;
  }else {
    task_status = 0;
    work_type = 0;
  }
  btn_TaskStep = document.getElementById("one_step");
  btn_NodeStep = document.getElementById("btnNodeStep");
  if(task_status===1 && work_type===0){ //执行中且是人工模式
    btn_TaskStep.disabled= false;
    btn_TaskStep.classList.remove("disabled-btn");
    //node-step
    if (selectedNodeData) {
      if(selectedNodeData.node_bwork){ //有选中node,且节点为工作状态
        btn_NodeStep.disabled= false;
        btn_NodeStep.classList.remove("disabled-btn");
      }
      else {
        btn_NodeStep.disabled = true;
        btn_NodeStep.classList.add("disabled-btn"); //css会去重
      }
    }
  }else{ //其他情况都是不可用状态
    btn_TaskStep.disabled = true;      // 添加 disabled 属性
    btn_TaskStep.classList.add("disabled-btn"); // 添加自定义样式
    if (selectedNodeData) {
      btn_NodeStep.disabled = true;
      btn_NodeStep.classList.add("disabled-btn"); //css会去重
    }
  }
}

//单步按钮--任务单步
document.getElementById("one_step").addEventListener("click",() => {
  if(cur_task_id===0){
    return
  }
  one_step_task();
});
async function one_step_task(){
  try {
      const res = await fetch("/api/task/taskstep", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ cur_task_id }),      //task_id:task_id
      });
      if (!res.ok) {
        const errorData = await res.json();
        throw new Error(errorData.error || `HTTP错误 ${res.status}`);
      }
      //修改成功
      const data = await res.json();
      const bsuccess = data.bsuccess;
      if(bsuccess){
        alert("该任务已提交单步工作,请稍候查看执行结果!")
      }
      else{
        error = data.error;
        alert("该任务单步失败!"+error)
      }
  }catch (error) {
      alert("该节点单步失败,请联系管理员!"+error);
  }
}

//------------------测试数据和漏洞数据tab-------------------
const pageSize = 10;
// 复用:根据返回的数据数组渲染表格 tbody,保证固定 10 行
function renderTableRows(tbody, rowsData) {
  tbody.innerHTML = "";
  // 遍历数据行,生成 <tr>
  rowsData.forEach((row, index) => {
    const tr = document.createElement("tr");
    // 这里假设 row 为对象,包含各个字段;下标从1开始显示序号
    for (const cellData of Object.values(row)) {
      const td = document.createElement("td");
      td.textContent = cellData;
      tr.appendChild(td);
    }
    tbody.appendChild(tr);
  });
  // 补足空行
  const rowCount = rowsData.length;
  for (let i = rowCount; i < pageSize; i++) {
    const tr = document.createElement("tr");
    for (let j = 0; j < tbody.parentElement.querySelectorAll("th").length; j++) {
      const td = document.createElement("td");
      td.innerHTML = "&nbsp;";
      tr.appendChild(td);
    }
    tbody.appendChild(tr);
  }
}

// 处理 CSV 字段,确保特殊字符正确转义
function escapeCsvField(value) {
  if (value == null) return "";
  const str = String(value).replace(/"/g, '""').replace(/\n/g, " ");
  return `"${str}"`; // 用引号包裹字段
}

//--------------------------测试指令-------------------------------
let allInstrs = [];
let currentInstrPage = 1;
function renderInstrPage(page) {
  currentInstrPage = page;
  const start = (page - 1) * pageSize;
  const end = start + pageSize;
  const pageData = allInstrs.slice(start, end);

  const tbody = document.querySelector("#instrTable tbody");
  renderTableRows(tbody, pageData);

  // 更新分页按钮
  document.getElementById("instrPrev").dataset.page = page > 1 ? page - 1 : 1;
  document.getElementById("instrNext").dataset.page = (end < allInstrs.length) ? page + 1 : page;
}

// 查询测试指令
async function searchInstructions(page = 1) {
  if(cur_task_id === 0){
    return;
  }
  const nodeName = document.getElementById("instrNodeName").value.trim();
  try {
    const res = await fetch("/api/task/getinstr", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        cur_task_id,
        nodeName
      }),
    });
    if (!res.ok) {
      const errorData = await res.json();
      throw new Error(errorData.error || `HTTP错误 ${res.status}`);
    }
    const data = await res.json();
    allInstrs = data.instrs;
    renderInstrPage(1); //显示第一页数据
  } catch (error) {
    console.error("获取测试指令失败:", error);
  }
}

//导出测试指令数据
async function ExportInstructions(){
  // Check if in secure context
    if (!window.isSecureContext) {
      console.error("Page is not in a secure context. Please load the page over HTTPS.");
      alert("无法导出文件:请使用 HTTPS 访问页面。");
      return;
    }

    // 如果 dataArr 为空,返回提示
    if (!allInstrs || allInstrs.length === 0) {
      alert("没有数据可导出");
      return;
    }

    // 在 CSV 的开头加上 BOM,用于 Excel 识别 UTF-8 编码
    let csv = "\uFEFF" + "序号,节点路径,执行指令,执行结果\n"; // 添加 BOM 防乱码
    allInstrs.forEach((item, i) => {
      csv +=
          [
            escapeCsvField(item[0] || ""),
            escapeCsvField(item[1] || ""),
            escapeCsvField(item[3] || ""),
            escapeCsvField(item[4] || ""),
          ].join(",") + "\n";
    });
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = "执行指令.csv";
    link.click();
    URL.revokeObjectURL(url);
}

// 绑定测试指令查询按钮事件
document.getElementById("instrSearchBtn").addEventListener("click", () => {
  searchInstructions();
});
// 绑定测试指令分页点击事件
document.getElementById("instrPrev").addEventListener("click", (e) => {
  const page = parseInt(e.target.dataset.page, 10);
  renderInstrPage(page);
});
document.getElementById("instrNext").addEventListener("click", (e) => {
  const page = parseInt(e.target.dataset.page, 10);
  renderInstrPage(page);
});

//------------------漏洞数据---------------------------------
let allVuls = [];
let currentVulPage = 1;
function renderVulPage(page) {
  currentVulPage = page;
  const start = (page - 1) * pageSize;
  const end = start + pageSize;
  const pageData = allVuls.slice(start, end);

  const tbody = document.querySelector("#vulTable tbody");
  renderTableRows(tbody, pageData);

  // 更新分页按钮
  document.getElementById("vulPrev").dataset.page = page > 1 ? page - 1 : 1;
  document.getElementById("vulNext").dataset.page = (end < allVuls.length) ? page + 1 : page;
}

// 查询漏洞数据
async function searchVulnerabilities(page = 1) {
  if(cur_task_id === 0){return;}
  const nodeName = document.getElementById("vulNodeName").value.trim();
  const vulType = document.getElementById("vulType").value.trim();
  const vulLevel = document.getElementById("vulLevel").value;
  try {
    const res = await fetch("/api/task/getvul", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        cur_task_id,
        nodeName,
        vulType,
        vulLevel
      }),
    });
    if (!res.ok) {
      const errorData = await res.json();
      throw new Error(errorData.error || `HTTP错误 ${res.status}`);
    }
    const data = await res.json();
    allVuls = data.vuls;
    renderVulPage(1)
  } catch (error) {
    console.error("获取漏洞数据失败:", error);
  }
}

//导出漏洞数据
async function ExportVuls(){
    // Check if in secure context
    if (!window.isSecureContext) {
      console.error("Page is not in a secure context. Please load the page over HTTPS.");
      alert("无法导出文件:请使用 HTTPS 访问页面。");
      return;
    }

    // 如果 dataArr 为空,返回提示
    if (!allVuls || allVuls.length === 0) {
      alert("没有数据可导出");
      return;
    }

    // 在 CSV 的开头加上 BOM,用于 Excel 识别 UTF-8 编码
    let csv = "\uFEFF" + "序号,节点路径,漏洞类型,漏洞级别,漏洞说明\n"; // 添加 BOM 防乱码
    allVuls.forEach((item, i) => {
      csv +=
          [
            escapeCsvField(item[0] || ""),
            escapeCsvField(item[1] || ""),
            escapeCsvField(item[2] || ""),
            escapeCsvField(item[3] || ""),
            escapeCsvField(item[4] || ""),
          ].join(",") + "\n";
    });
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = "漏洞数据.csv";
    link.click();
    URL.revokeObjectURL(url);
}

// 绑定漏洞数据查询按钮事件
document.getElementById("vulSearchBtn").addEventListener("click", () => {
  searchVulnerabilities();
});
// 绑定漏洞数据分页点击事件
document.getElementById("vulPrev").addEventListener("click", (e) => {
  const page = parseInt(e.target.dataset.page, 10);
  renderVulPage(page);
});
document.getElementById("vulNext").addEventListener("click", (e) => {
  const page = parseInt(e.target.dataset.page, 10);
  renderVulPage(page);
});