<template>
  <!-- 唯一根节点：el-card -->
  <el-card class="el-content-wrap mb-3px" shadow="never">
    <!-- 标题 + 提示 -->
    <template v-if="title" slot="header">
      <div class="flex items-center">
        <span class="text-16px font-700">{{ title }}</span>
        <el-tooltip v-if="message" effect="dark" placement="right">
          <template slot="content">
            <div class="max-w-200px">{{ message }}</div>
          </template>
          <i class="el-icon-question ml-5px" style="font-size: 14px" />
        </el-tooltip>
      </div>
    </template>

    <!-- 原 content-wrap 的 slot 内容 -->
    <el-row class="mb-10px">
      <template v-for="btn in dynamicButtons">
        <el-button
          v-if="!btn.ifHide"
          :key="btn.id"
          type="primary"
          size="small"
          @click="handleDynamicButtonClick(btn)"
        >
          {{ btn.buttonName }}
        </el-button>
      </template>

      <el-button size="small" type="danger" @click="AllConditionReset">
        <i class="el-icon-refresh mr-5px" style="font-size: 14px" />
        全条件重置
      </el-button>

      <el-button size="small" type="primary" @click="Export">
        <i class="el-icon-download mr-5px" style="font-size: 14px" />
        导出
      </el-button>

      <el-button
        size="small"
        type="success"
        :loading="exportLoading"
        @click="ExportAll"
      >
        <i class="el-icon-download mr-5px" style="font-size: 14px" />
        导出全部
      </el-button>

      <el-button size="small" @click="handleBack">
        <i class="el-icon-arrow-left mr-5px" style="font-size: 14px" />
        返回
      </el-button>
    </el-row>

    <!-- 表格 -->
    <el-table
      id="table_excel"
      ref="tableRef"
      v-loading="loading"
      :data="list"
      stripe
      border
      size="small"
      max-height="calc(100vh - 230px)"
      show-overflow-tooltip
      show-summary
      :summary-method="getSummaries"
      @selection-change="handleSelectionChange"
      @header-dragend="handleResize"
    >
      <el-table-column
        v-if="showMultipleList.length"
        type="selection"
        width="55"
      />
      <el-table-column type="index" width="55" align="center" />

      <template v-for="(item, i) in queryData">
        <el-table-column
          v-if="!item.ifHide"
          :key="i"
          :label="item.columnComment"
          :prop="item.columnComment"
          align="center"
          :min-width="item.javaField || ''"
          :sortable="false"
          show-overflow-tooltip
        >
          <template slot="header">
            <div class="mr-5px flex items-center">
              <!-- 排序图标 -->
              <div v-show="item.ifSort" class="mr-5px flex flex-col gap-0">
                <i
                  class="el-icon-caret-top"
                  style="font-size: 15px; cursor: pointer"
                  :class="{
                    'is-sort':
                      currentSortField === item.columnComment &&
                      currentSortDirection === 'asc',
                  }"
                  @click="handleSort(item.columnComment, 'asc')"
                />
                <i
                  ref=""
                  class="el-icon-caret-bottom -mt-1.2"
                  style="font-size: 15px; cursor: pointer"
                  :class="{
                    'is-sort':
                      currentSortField === item.columnComment &&
                      currentSortDirection === 'desc',
                  }"
                  @click="handleSort(item.columnComment, 'desc')"
                />
              </div>

              <span>{{ item.columnComment }}</span>

              <!-- 列过滤 -->
              <FilterColumnInQuery
                v-if="item.listOperationResult"
                :label="item.columnComment"
                :prop="item.columnName"
                :filter-list="queryData"
                :query-id="$route.query.id"
                :filter-list-key="item.columnName"
                order-type="queryManage"
                :param-list="queryParamList"
                :active-filters="customFilters"
                :html-type="item.htmlType"
                :dict-type="item.dictType"
                :is-clear="isClear"
                @select-data="
                  (data, field, htmlType) =>
                    filterData(data, field, htmlType, item)
                "
              >
                <template slot="reference">
                  <div
                    class="flex items-center justify-center text-gray-600"
                    :class="{ 'has-filter': hasFilter(item.columnName) }"
                  >
                    <svg-icon
                      icon-class="search"
                      class="ml-2px"
                      style="font-size: 14px; cursor: pointer"
                    />
                  </div>
                </template>
              </FilterColumnInQuery>
            </div>
          </template>

          <template slot-scope="{ row }">
            <div
              :class="{ active: item.example }"
              @click="
                pathChange(item.example, row[item.columnComment], item, row)
              "
            >
              <dict-tag
                v-if="
                  isDict(item.columnComment) &&
                  ![undefined, null].includes(row[item.columnComment])
                "
                :type="isDict(item.columnComment)"
                :value="row[item.columnComment]"
              />
              <span
                v-else-if="
                  row[item.columnComment] && isDateTime(item.columnComment)
                "
              >
                {{ formatToDateTime(row[item.columnComment]) }}
              </span>
              <span v-else>{{ row[item.columnComment] }}</span>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <!-- 分页 -->
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="pageNo"
      :limit.sync="pageSize"
      @pagination="handleSearch"
    />

    <!-- 弹窗 -->
    <ReportPrint ref="reportPrint" />
    <ParameterDetail ref="parameterDetailRef" @success="getQueryData" />
  </el-card>
</template>

<script>
import * as QueryManageApi from "@/api/mes/queryManage";
import { getQueryManageButtonPage } from "@/api/mes/queryManage/button";
import { saveAs } from "file-saver";
import * as XLSX from "xlsx";
import FilterColumnInQuery from "./components/FilterColumnInQuery.vue";
import DictTag from "./components/DictTag.vue";
import ParameterDetail from "./components/ParameterDetail.vue";
import ReportPrint from "./components/ReportPrint.vue";
import request from "@/utils/request";
import { getAccessToken, getTenantId } from "@/utils/auth";
import axios from "axios";

export default {
  name: "QueryForm",
  components: {
    FilterColumnInQuery,
    ParameterDetail,
    ReportPrint,
    DictTag,
  },
  data() {
    return {
      title: "", // ContentWrap 的 title
      message: "", // ContentWrap 的 message
      queryList: [],
      searchData: [],
      queryData: [],
      list: [],
      originalList: [],
      pageNo: 1,
      pageSize: 20,
      total: 0,
      loading: false,
      form: {},
      visible: false,
      customFilters: {},
      currentSortField: null,
      currentSortDirection: null,
      dynamicButtons: [],
      queryParamList: [],
      exportLoading: false,
      showMultipleList: [],
      isClear: false,
      multipleSelection: [],
      headerWidthChange: false,
    };
  },
  mounted() {
    this.init();
  },
  activated() {
    this.init();
  },
  beforeDestroy() {
    this.saveColumnWidth();
  },
  methods: {
    /* 生命周期 */
    async init() {
      this.title =
        this.$route.query?.name ||
        this.$route.redirectedFrom?.meta?.title ||
        "查询";
      // 需要提示文字时，再写 this.message = 'xxx'
      if (this.$route.query.infraQueryId) {
        await this.getFilterData();
      } else {
        this.buildQueryParamFromRoute();
        await this.getQueryData();
      }
    },

    /* 以下所有方法保持与原文件一致，不再赘述 */
    async getQueryData() {
      try {
        this.loading = true;
        const data = await QueryManageApi.getQueryManageColumnListByMasterId(
          this.$route.query.id
        );
        // 确保queryData是数组
        this.queryData = Array.isArray(data.data) ? data.data || [] : [];
        console.log("queryData长度", this.queryData.length);
        this.searchData = this.queryData.filter(
          (item) => item.listOperationResult && item.ifHide === false
        );
        this.showMultipleList = this.queryData.filter(
          (item) => item.listOperationCondition === "1"
        );
        this.queryList = [];
        for (let i = 0; i < this.searchData.length; i++) {
          const { dataType, htmlType, dictType, columnName } =
            this.searchData[i];
          this.queryList.push({
            dataType,
            htmlType,
            dictType,
            key: columnName,
            operate: dataType === "ym_string_query_type" ? "like" : "",
          });
        }
        await this.getManageButtons(this.$route.query?.id);
        await this.getList();
      } finally {
        this.loading = false;
      }
    },

    async getList() {
      console.log("getList被调用，queryParamList:", this.queryParamList);
      try {
        this.loading = true;
        console.log("调用QueryManageApi.loadTableData，参数:", {
          pageNo: this.pageNo,
          pageSize: this.pageSize,
          paramList: this.queryParamList,
          id: this.$route.query?.id,
        });
        const data = await QueryManageApi.loadTableData({
          pageNo: this.pageNo,
          pageSize: this.pageSize,
          paramList: this.queryParamList,
          id: this.$route.query?.id,
        });
        console.log("后端返回", data);
        this.list = data?.data?.list || [];
        console.log("赋值后 list =", this.list);
        console.log("list.length =", this.list.length);
        console.log("list 第一条 =", this.list[0]);
        this.originalList = JSON.parse(JSON.stringify(data?.data?.list || []));
        this.total = data?.data?.total || 0;
      } catch (error) {
        console.error("getList错误:", error);
      } finally {
        this.loading = false;
      }
    },

    async getManageButtons(masterId) {
      const data = await getQueryManageButtonPage({ masterId });
      this.dynamicButtons = data?.data?.list || [];
    },

    async handleDynamicButtonClick(btn = {}) {
      const {
        ifJimu,
        interfaceUrl,
        printSoft,
        operateType,
        paramList = [],
      } = btn;
      if (ifJimu) {
        this.handlePrintByJimu(btn);
      } else if (this.isFullUrl(interfaceUrl) && printSoft) {
        this.handlePrintByOtherSoft(btn);
      } else if (operateType === 2) {
        this.$refs.parameterDetailRef.open(
          "create",
          btn,
          this.$route.query?.id,
          [],
          this.queryData
        );
      } else if (operateType === 3) {
        if (this.multipleSelection.length === 0)
          return this.$message.warning("请先选择行数据!");
        if (this.multipleSelection.length > 1)
          return this.$message.warning("只能选择单条数据修改!");
        this.$refs.parameterDetailRef.open(
          "update",
          btn,
          this.$route.query?.id,
          this.multipleSelection,
          this.queryData
        );
      } else if (operateType === 7) {
        this.$router.push({ path: `${interfaceUrl}` });
      } else {
        this.handleDynamic(btn);
      }
    },

    formatToDateTime(val) {
      const d = val ? new Date(val) : new Date();
      if (isNaN(d.getTime())) return "";
      const pad = (n) => String(n).padStart(2, "0");
      return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(
        d.getDate()
      )} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
    },

    handlePrintByJimu(params) {
      if (this.multipleSelection.length === 0)
        return this.$message.warning("请先选择数据!");
      const baseUrl = process.env.VITE_BASE_URL;
      const token = getAccessToken();
      const tenantId = getTenantId();
      const { paramList = [], interfaceUrl, reportId } = params;
      const fieldValues = this.paramsToConver(paramList);
      const printParams = new URLSearchParams({
        token,
        tenantId,
        ...fieldValues,
      });
      const src = `${baseUrl}${interfaceUrl}${reportId}?${printParams.toString()}`;
      this.$refs.reportPrint.open(
        src,
        this.$route.query?.name ||
          this.$route.redirectedFrom?.meta?.title ||
          "报表打印"
      );
    },

    async handlePrintByOtherSoft(params) {
      if (this.multipleSelection.length === 0)
        return this.$message.warning("请先选择数据!");
      const { interfaceUrl, paramList, restMethod, templet } = params;
      if (!templet) return this.$message.warning("未配置打印模板!");
      const fieldValues = this.paramsToConver(paramList);
      const printParams = { ...fieldValues, fileUrl: templet };
      const config = {
        method: restMethod,
        url: interfaceUrl,
        [restMethod === "get" || restMethod === "delete" ? "params" : "data"]:
          printParams,
      };
      await axios(config);
      this.$message.success("操作成功!");
      this.getList();
    },

    async handleDynamic(params) {
      if (this.multipleSelection.length === 0)
        return this.$message.warning("请先选择数据!");
      const {
        interfaceUrl,
        restMethod = "get",
        paramList = [],
        requestParameter = "0",
      } = params;
      const fieldValues = this.paramsToConver(paramList);
      const config = { method: restMethod, url: interfaceUrl };
      this.handleGetDelete(config, fieldValues, requestParameter);
      await request[restMethod]?.(config);
      this.$message.success("操作成功");
      this.getList();
    },

    handleGetDelete(config, fieldValues, requestParameter) {
      switch (requestParameter) {
        case "1":
          config.params = fieldValues;
          break;
        case "3":
          config.url = new URLSearchParams(fieldValues).toString()
            ? `${config.url}?${new URLSearchParams(fieldValues).toString()}`
            : config.url;
          break;
        case "4":
          config.headers = { ...config.headers, ...fieldValues };
          break;
        default:
          config.data = fieldValues;
      }
    },

    paramsToConver(paramList) {
      const matchListWithParam = paramList
        ?.filter((item) =>
          this.queryData.some((query) => item.columnId === query?.id)
        )
        .map((item) => {
          const paramItem = this.queryData.find(
            (query) => item.columnId === query?.id
          );
          return { ...item, columnComment: paramItem?.columnComment };
        });
      const result = this.generateMappedData(
        this.multipleSelection,
        matchListWithParam
      );
      const allFields = [...new Set(result.flatMap(Object.keys))];
      return allFields.reduce((acc, field) => {
        acc[field] = result.map((item) => item[field]).join(",");
        return acc;
      }, {});
    },

    generateMappedData(selectList, keys) {
      return selectList.map((item) =>
        keys.reduce((res, key) => {
          const { columnComment, paramName } = key;
          if (item.hasOwnProperty(columnComment)) {
            const field = paramName.split(".").pop();
            res[field] = item[columnComment];
          }
          return res;
        }, {})
      );
    },

    isFullUrl(url) {
      try {
        const parsed = new URL(url);
        return parsed.protocol === "http:" || parsed.protocol === "https:";
      } catch {
        return false;
      }
    },

    isDict(key) {
      if (!Array.isArray(this.queryData)) return false;
      const item = this.queryData.find((item) => item.columnComment === key);
      return item ? item.dictType : false;
    },

    isNumber(key) {
      if (!Array.isArray(this.queryData)) return false;
      const item = this.queryData.find((item) => item.columnComment === key);
      return item && item.dataType === "ym_int_query_type";
    },

    isDateTime(key) {
      if (!Array.isArray(this.queryData)) return false;
      const item = this.queryData.find((item) => item.columnComment === key);
      return item && item.javaType === "LocalDateTime";
    },

    hasFilter(field) {
      return !!(this.customFilters[field] && this.customFilters[field].length);
    },

    handleSort(field, direction) {
      if (
        this.currentSortField === field &&
        this.currentSortDirection === direction
      ) {
        this.currentSortField = "";
        this.currentSortDirection = "";
        this.list = JSON.parse(JSON.stringify(this.originalList));
        return;
      }
      this.currentSortField = field;
      this.currentSortDirection = direction;
      this.list = [...this.originalList].sort((a, b) => {
        let valA = a[field];
        let valB = b[field];
        valA =
          typeof valA === "string" ? parseFloat(valA.replace(/,/g, "")) : valA;
        valB =
          typeof valB === "string" ? parseFloat(valB.replace(/,/g, "")) : valB;
        if (isNaN(valA))
          return direction === "asc"
            ? valA > valB
              ? 1
              : -1
            : valA < valB
            ? 1
            : -1;
        if (isNaN(valB))
          return direction === "asc"
            ? valA > valB
              ? 1
              : -1
            : valA < valB
            ? 1
            : -1;
        return direction === "asc" ? valA - valB : valB - valA;
      });
    },

    filterData(data, field, type, row) {
      console.log("filterData被调用:", { data, field, type, row });
      const { dataType } = row;
      this.$set(this.customFilters, field, data);
      const isDateRange = data[0]?.isRange;
      if (isDateRange) {
        const valueList = data.flatMap((item) => item.column).join(",");
        const idx = this.queryParamList.findIndex((item) => item.key === field);
        if (idx > -1) {
          this.queryParamList[idx].value = valueList;
        } else {
          this.queryParamList.push({
            key: field,
            operate: "like",
            htmlType: type,
            value: valueList,
          });
        }
        console.log(
          "filterData - 日期范围筛选后queryParamList:",
          this.queryParamList
        );
        this.getList();
        return;
      }
      let valueStr;
      if (data.length) {
        valueStr =
          dataType === "ym_int_query_type"
            ? data.map((item) => item.column).join(",")
            : data.map((item) => `'${item.column}'`).join(",");
        const idx = this.queryParamList.findIndex((item) => item.key === field);
        if (idx > -1) {
          this.queryParamList[idx].value = valueStr;
        } else {
          this.queryParamList.push({
            key: field,
            operate: "like",
            htmlType: type,
            value: valueStr,
          });
        }
      } else {
        const idx = this.queryParamList.findIndex((item) => item.key === field);
        if (idx > -1) this.queryParamList.splice(idx, 1);
      }
      console.log("filterData - 筛选后queryParamList:", this.queryParamList);
      this.getList();
    },

    AllConditionReset() {
      this.queryParamList = [];
      this.customFilters = {};
      this.isClear = true;
      setTimeout(() => (this.isClear = false), 1000);
      this.getList();
    },

    handleSearch() {
      this.list = [];
      this.getList();
    },

    async Export() {
      try {
        await this.$confirm("确定导出当前页？", "提示", { type: "warning" });
        setTimeout(() => {
          const xlsxParam = { raw: true };
          const tables = document.getElementById("table_excel");
          const table_book = XLSX.utils.table_to_book(tables, xlsxParam);
          const tableWrite = XLSX.write(table_book, {
            bookType: "xlsx",
            bookSST: true,
            type: "array",
          });
          saveAs(
            new Blob([tableWrite], { type: "application/octet-stream" }),
            `${this.title}.xlsx`
          );
        }, 1000);
      } catch {}
    },

    async ExportAll() {
      try {
        await this.$confirm("确定导出全部？", "提示", { type: "warning" });
        this.exportLoading = true;
        const data = await QueryManageApi.exportExcel({
          id: this.$route.query?.id,
          paramList: this.queryParamList,
        });
        this.$download.excel(data, this.title + ".xls");
      } finally {
        this.exportLoading = false;
      }
    },

    getHandleNumber(val) {
      return Math.round(parseFloat(val) * 100000000) / 100000000;
    },

    getSummaries({ columns }) {
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "总计";
          return;
        }
        const values = this.list.map((item) => Number(item[column.property]));
        if (this.isNumber(column.property)) {
          sums[index] = values.reduce((acc, cur) => {
            const value = Number(cur);
            return !isNaN(value) ? this.getHandleNumber(acc + cur) : acc;
          }, 0);
        }
      });
      return sums;
    },

    handleSelectionChange(val) {
      this.multipleSelection = val;
    },

    pathChange(path, val, item, row) {
      if (path === "sameRouter") return;
      if (!path) return;
      const data = {};
      this.dynamicButtons
        .filter((v) => v.ifHide && v.paramList.length)
        .forEach((v) =>
          v.paramList.forEach((val) => {
            data[val.paramName] = val.value || row[val.paramComment];
          })
        );
      this.$router.push({ path: `${path}`, query: { id: val, ...data } });
    },

    handleBack() {
      this.$router.push({ path: "/querymanage/queryManageIndex" });
    },

    handleResize() {
      this.headerWidthChange = true;
    },

    async saveColumnWidth() {
      if (!this.headerWidthChange) return;
      this.headerWidthChange = false;
      const widthList = [];
      // 确保queryData是数组
      if (!Array.isArray(this.queryData)) return;

      const headers = this.$refs.tableRef.$el.querySelectorAll(
        ".el-table__header-wrapper tr th"
      );
      const visibleColumns = this.queryData.filter((item) => !item.ifHide);
      const validHeaders = [...headers].filter(
        (th) =>
          !th.classList.contains("el-table-column--selection") &&
          th.innerText.trim() !== ""
      );
      validHeaders.forEach((header, i) => {
        const correspondingItem = visibleColumns[i];
        if (correspondingItem) {
          widthList.push({
            id: correspondingItem.id,
            javaField: header.offsetWidth,
          });
        }
      });
      await QueryManageApi.updateWidth(widthList);
    },

    buildQueryParamFromRoute() {
      const queryParam = [];
      for (const i in this.$route.query) {
        if (i !== "id" && i !== "name") {
          queryParam.push({
            key: i,
            operate: "like",
            htmlType: "input",
            value: "'" + this.$route.query[i] + "'",
          });
        }
      }
      this.queryParamList = queryParam;
    },

    async getFilterData() {
      const data = await getQueryManageButtonPage({
        masterId: this.$route.query?.infraQueryId,
      });
      const arr = [];
      data.list
        .filter((v) => v.ifHide && v.paramList.length)
        .forEach((v) =>
          v.paramList.forEach((val) => {
            if (val.filter) arr.push(val.paramName);
          })
        );
      const queryParam = [];
      for (const i in this.$route.query) {
        if (arr.indexOf(i) > -1) {
          queryParam.push({
            key: i,
            operate: "like",
            htmlType: "input",
            value: "'" + this.$route.query[i] + "'",
          });
        }
      }
      this.queryParamList = queryParam;
      await this.getQueryData();
    },
  },
};
</script>

<style scoped lang="scss">
/* ---------- ContentWrap 原样式 ---------- */
.el-content-wrap {
  /* 自定义 */
}
.text-16px {
  font-size: 16px;
}
.font-700 {
  font-weight: 700;
}
.ml-5px {
  margin-left: 5px;
}
.max-w-200px {
  max-width: 200px;
}
.mb-3px {
  margin-bottom: 3px;
}

/* ---------- 原来的表格样式 ---------- */
:deep(.el-table__row) {
  height: 15px !important;
}
.el-table--medium .el-table__cell,
.el-table--small .el-table__cell {
  padding: 1px 0 !important;
}
.active:hover {
  cursor: pointer;
}
.has-filter,
.is-sort,
.active {
  color: #1890ff !important;
}
</style>
