<template>
  <div class="app-container">
    <el-tabs v-model="centerTab" type="border-card">
      <el-tab-pane label="资产中心" name="asset">
        <el-row :gutter="12" class="mb8">
          <el-col :span="8">
            <el-card shadow="never" class="asset-card">
              <div slot="header"><span>模板资产</span></div>
              <el-table :data="assetTemplates" size="mini" max-height="280">
                <el-table-column label="报表名称" prop="reportName" min-width="140" />
                <el-table-column label="模式" prop="queryMode" width="110" />
                <el-table-column label="操作" width="80">
                  <template slot-scope="scope">
                    <el-button type="text" size="mini" @click="useTemplate(scope.row)">使用</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-card>
          </el-col>
          <el-col :span="8">
            <el-card shadow="never" class="asset-card">
              <div slot="header"><span>指标资产</span></div>
              <el-table :data="assetMetrics" size="mini" max-height="280">
                <el-table-column label="字段键" prop="fieldKey" min-width="110" />
                <el-table-column label="聚合" prop="aggregateFn" width="80" />
                <el-table-column label="次数" prop="usedCount" width="80" />
              </el-table>
            </el-card>
          </el-col>
          <el-col :span="8">
            <el-card shadow="never" class="asset-card">
              <div slot="header"><span>数据集资产</span></div>
              <el-table :data="metaTables" size="mini" max-height="280">
                <el-table-column label="表名" prop="tableName" min-width="120" />
                <el-table-column label="注释" prop="tableComment" min-width="120" show-overflow-tooltip />
              </el-table>
            </el-card>
          </el-col>
        </el-row>

        <el-form ref="queryForm" :model="queryParams" :inline="true" size="small" label-width="84px">
          <el-form-item label="报表编码" prop="reportCode">
            <el-input v-model="queryParams.reportCode" placeholder="请输入报表编码" clearable style="width: 220px" />
          </el-form-item>
          <el-form-item label="报表名称" prop="reportName">
            <el-input v-model="queryParams.reportName" placeholder="请输入报表名称" clearable style="width: 220px" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>

        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['erp:report:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['erp:report:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['erp:report:remove']">删除</el-button>
          </el-col>
          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
        </el-row>

        <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column label="ID" prop="id" align="center" width="80" />
          <el-table-column label="报表编码" prop="reportCode" align="center" min-width="130" />
          <el-table-column label="报表名称" prop="reportName" align="center" min-width="160" />
          <el-table-column label="查询模式" prop="queryMode" align="center" width="110" />
          <el-table-column label="聚合模式" prop="aggregateMode" align="center" width="110" />
          <el-table-column label="状态" prop="status" align="center" width="110" />
          <el-table-column label="操作" align="center" width="220">
            <template slot-scope="scope">
              <el-button size="mini" type="text" icon="el-icon-setting" @click="selectWorkbenchReport(scope.row)">进入工作台</el-button>
              <el-button size="mini" type="text" icon="el-icon-upload" @click="handlePublish(scope.row)" v-hasPermi="['erp:report:publish']">发布</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-tab-pane>

      <el-tab-pane label="构建工作台" name="workbench">
        <el-card shadow="never">
          <el-form :inline="true" size="small" label-width="90px">
            <el-form-item label="当前报表">
              <el-select v-model="workbenchReportId" filterable placeholder="请选择报表" style="width: 320px" @change="onWorkbenchReportChange">
                <el-option v-for="item in list" :key="item.id" :label="`${item.reportName}(${item.reportCode})`" :value="item.id" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" size="mini" @click="loadWorkbenchDesign">加载设计</el-button>
              <el-button size="mini" @click="handlePreviewWorkbench">预览SQL与结果</el-button>
              <el-button type="success" size="mini" @click="saveWorkbenchDesign">保存设计</el-button>
            </el-form-item>
          </el-form>

          <el-alert
            type="info"
            :closable="false"
            title="构建工作台统一承载低代码配置与高级SQL配置。推荐先选表选字段，复杂场景再使用SQL模式。"
            style="margin-bottom: 10px"
          />

          <el-form inline size="small" style="margin-bottom: 6px">
            <el-form-item label="主表">
              <el-select v-model="designMainTable" filterable placeholder="请选择主表" style="width: 280px">
                <el-option v-for="item in metaTables" :key="item.tableName" :label="formatTableLabel(item)" :value="item.tableName" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button size="mini" plain @click="appendMainTableColumns">主表字段批量加入</el-button>
            </el-form-item>
          </el-form>

          <el-tabs v-model="designTab">
            <el-tab-pane label="字段配置" name="fields">
              <div class="mb8">
                <el-button size="mini" type="primary" plain icon="el-icon-plus" @click="handleAddField">新增字段</el-button>
              </div>
              <el-table :data="designForm.fields" border size="mini">
                <el-table-column label="#" type="index" width="50" align="center" />
                <el-table-column label="字段键" min-width="120">
                  <template slot-scope="scope"><el-input v-model="scope.row.fieldKey" size="mini" /></template>
                </el-table-column>
                <el-table-column label="来源表" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.sourceTable" filterable size="mini" @change="onFieldTableChange(scope.row)">
                      <el-option v-for="item in metaTables" :key="item.tableName" :label="formatTableLabel(item)" :value="item.tableName" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="来源字段" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.sourceColumn" filterable size="mini" @change="onFieldColumnChange(scope.row)">
                      <el-option
                        v-for="item in getTableColumns(scope.row.sourceTable)"
                        :key="`${scope.row.sourceTable}_${item.columnName}`"
                        :label="formatColumnLabel(item)"
                        :value="item.columnName"
                      />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="表达式" min-width="160">
                  <template slot-scope="scope"><el-input v-model="scope.row.exprText" size="mini" /></template>
                </el-table-column>
                <el-table-column label="聚合" width="110">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.aggregateFn" size="mini" clearable>
                      <el-option label="SUM" value="SUM" />
                      <el-option label="AVG" value="AVG" />
                      <el-option label="MAX" value="MAX" />
                      <el-option label="MIN" value="MIN" />
                      <el-option label="COUNT" value="COUNT" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="分组" width="90" align="center">
                  <template slot-scope="scope"><el-switch v-model="scope.row._groupSwitch" @change="onGroupSwitchChange(scope.row)" /></template>
                </el-table-column>
                <el-table-column label="操作" width="70" align="center">
                  <template slot-scope="scope"><el-button type="text" size="mini" @click="handleRemoveField(scope.$index)">删除</el-button></template>
                </el-table-column>
              </el-table>
            </el-tab-pane>

            <el-tab-pane label="关联配置" name="joins">
              <div class="mb8">
                <el-button size="mini" type="primary" plain icon="el-icon-plus" @click="handleAddJoin">新增关联</el-button>
              </div>
              <el-table :data="designForm.joins" border size="mini">
                <el-table-column label="#" type="index" width="50" align="center" />
                <el-table-column label="左表" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.leftTable" filterable size="mini" @change="onJoinLeftTableChange(scope.row)">
                      <el-option v-for="item in metaTables" :key="`left_${item.tableName}`" :label="formatTableLabel(item)" :value="item.tableName" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="左字段" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.leftColumn" filterable size="mini">
                      <el-option
                        v-for="item in getTableColumns(scope.row.leftTable)"
                        :key="`lc_${scope.row.leftTable}_${item.columnName}`"
                        :label="formatColumnLabel(item)"
                        :value="item.columnName"
                      />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="关联类型" width="110">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.joinType" size="mini">
                      <el-option label="INNER" value="INNER" />
                      <el-option label="LEFT" value="LEFT" />
                      <el-option label="RIGHT" value="RIGHT" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="右表" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.rightTable" filterable size="mini" @change="onJoinRightTableChange(scope.row)">
                      <el-option v-for="item in metaTables" :key="`right_${item.tableName}`" :label="formatTableLabel(item)" :value="item.tableName" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="右字段" min-width="120">
                  <template slot-scope="scope">
                    <el-select v-model="scope.row.rightColumn" filterable size="mini">
                      <el-option
                        v-for="item in getTableColumns(scope.row.rightTable)"
                        :key="`rc_${scope.row.rightTable}_${item.columnName}`"
                        :label="formatColumnLabel(item)"
                        :value="item.columnName"
                      />
                    </el-select>
                  </template>
                </el-table-column>
              </el-table>
            </el-tab-pane>

            <el-tab-pane label="高级SQL模式" name="sql">
              <el-alert type="warning" :closable="false" title="高级SQL仅允许SELECT，且发布前会做安全校验。" />
              <el-input style="margin-top: 10px" type="textarea" :rows="10" v-model="designForm.customSql" placeholder="请输入自定义 SQL（仅 SELECT）" />
            </el-tab-pane>
          </el-tabs>

          <el-divider />
          <el-form label-width="90px" size="mini">
            <el-form-item label="预览SQL">
              <el-input type="textarea" :rows="4" :value="previewData.generatedSql || '-'" readonly />
            </el-form-item>
          </el-form>
          <el-table :data="previewData.rows || []" size="mini" max-height="260">
            <el-table-column v-for="key in previewColumns" :key="key" :label="key" :prop="key" min-width="140" show-overflow-tooltip />
          </el-table>
        </el-card>
      </el-tab-pane>

      <el-tab-pane label="发布中心" name="publish">
        <el-card shadow="never">
          <el-form :inline="true" size="small" label-width="90px">
            <el-form-item label="目标报表">
              <el-select v-model="publishReportId" filterable placeholder="请选择报表" style="width: 320px">
                <el-option v-for="item in list" :key="item.id" :label="`${item.reportName}(${item.reportCode})`" :value="item.id" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" size="mini" @click="runPublishChecks">执行发布前检查</el-button>
              <el-button type="success" size="mini" @click="publishSelected">发布</el-button>
              <el-button type="warning" size="mini" @click="diagnoseSelectedMenu">菜单诊断/补建</el-button>
              <el-button size="mini" @click="handleRebuildMenus">全量重建菜单</el-button>
            </el-form-item>
          </el-form>

          <el-row :gutter="12" class="mb8">
            <el-col :span="8">
              <el-card shadow="hover">
                <div slot="header">SQL安全检查</div>
                <el-tag :type="publishChecks.sqlSafe ? 'success' : 'danger'">{{ publishChecks.sqlSafe ? "通过" : "未通过" }}</el-tag>
              </el-card>
            </el-col>
            <el-col :span="8">
              <el-card shadow="hover">
                <div slot="header">预览数据检查</div>
                <el-tag :type="publishChecks.previewOk ? 'success' : 'warning'">{{ publishChecks.previewOk ? "通过" : "待确认" }}</el-tag>
              </el-card>
            </el-col>
            <el-col :span="8">
              <el-card shadow="hover">
                <div slot="header">菜单权限同步提示</div>
                <el-tag :type="publishChecks.menuHint ? 'success' : 'info'">{{ publishChecks.menuHint ? "已具备同步条件" : "待执行发布" }}</el-tag>
              </el-card>
            </el-col>
          </el-row>

          <el-alert type="info" :closable="false" :title="publishTip" />
        </el-card>
      </el-tab-pane>
    </el-tabs>

    <el-dialog :title="title" :visible.sync="open" width="620px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
        <el-row>
          <el-col :span="12"><el-form-item label="报表编码" prop="reportCode"><el-input v-model="form.reportCode" :disabled="!!form.id" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="报表名称" prop="reportName"><el-input v-model="form.reportName" /></el-form-item></el-col>
        </el-row>
        <el-row>
          <el-col :span="12"><el-form-item label="数据源" prop="dataSource"><el-input v-model="form.dataSource" /></el-form-item></el-col>
          <el-col :span="12">
            <el-form-item label="状态" prop="status">
              <el-select v-model="form.status" style="width: 100%">
                <el-option label="草稿" value="DRAFT" />
                <el-option label="已发布" value="PUBLISHED" />
                <el-option label="禁用" value="DISABLED" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="查询模式" prop="queryMode">
              <el-select v-model="form.queryMode" style="width: 100%">
                <el-option label="低代码" value="LOW_CODE" />
                <el-option label="自定义SQL" value="CUSTOM_SQL" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="聚合模式" prop="aggregateMode">
              <el-select v-model="form.aggregateMode" style="width: 100%">
                <el-option label="实时聚合" value="REALTIME" />
                <el-option label="离线聚合" value="OFFLINE" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  addReportDefinition,
  deleteReportDefinition,
  getReportDefinition,
  getReportDesign,
  listReportAssetMetrics,
  listReportAssetTemplates,
  listReportMetaFields,
  listReportMetaTables,
  menuDiagnosticByReportId,
  rebuildPublishedReportMenus,
  listReportDefinition,
  publishReportDefinition,
  saveReportDesign,
  updateReportDefinition
} from "@/api/report/definition";
import { previewReportRuntime } from "@/api/erp/runtime";

export default {
  name: "ReportDefinition",
  data() {
    return {
      centerTab: "asset",
      loading: false,
      showSearch: true,
      list: [],
      total: 0,
      ids: [],
      single: true,
      multiple: true,
      open: false,
      title: "",
      workbenchReportId: undefined,
      publishReportId: undefined,
      publishTip: "请先选择目标报表并执行发布前检查。",
      publishChecks: { sqlSafe: false, previewOk: false, menuHint: false },
      assetTemplates: [],
      assetMetrics: [],
      metaTables: [],
      tableColumnsMap: {},
      designMainTable: "",
      designTab: "fields",
      designForm: {
        fields: [],
        joins: [],
        customSql: ""
      },
      previewData: {
        dataSourceMode: "",
        total: 0,
        rows: [],
        generatedSql: ""
      },
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        reportCode: undefined,
        reportName: undefined
      },
      form: {},
      rules: {
        reportCode: [{ required: true, message: "报表编码不能为空", trigger: "blur" }],
        reportName: [{ required: true, message: "报表名称不能为空", trigger: "blur" }],
        dataSource: [{ required: true, message: "数据源不能为空", trigger: "blur" }],
        queryMode: [{ required: true, message: "查询模式不能为空", trigger: "change" }],
        aggregateMode: [{ required: true, message: "聚合模式不能为空", trigger: "change" }]
      }
    };
  },
  computed: {
    previewColumns() {
      const rows = this.previewData.rows || [];
      if (!rows.length) return [];
      return Object.keys(rows[0] || {});
    }
  },
  created() {
    this.getList();
    this.loadAssetCenter();
  },
  methods: {
    loadAssetCenter() {
      listReportMetaTables().then((res) => {
        this.metaTables = res.data || [];
      });
      listReportAssetTemplates().then((res) => {
        this.assetTemplates = res.data || [];
      });
      listReportAssetMetrics().then((res) => {
        this.assetMetrics = res.data || [];
      });
    },
    getList() {
      this.loading = true;
      listReportDefinition(this.queryParams)
        .then((res) => {
          this.list = res.rows || [];
          this.total = res.total || 0;
        })
        .finally(() => {
          this.loading = false;
        });
    },
    reset() {
      this.form = {
        id: undefined,
        reportCode: undefined,
        reportName: undefined,
        dataSource: "business_db",
        queryMode: "LOW_CODE",
        aggregateMode: "REALTIME",
        status: "DRAFT"
      };
      this.resetForm("form");
    },
    cancel() {
      this.open = false;
      this.reset();
    },
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    handleSelectionChange(selection) {
      this.ids = selection.map((item) => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "新增报表定义";
    },
    handleUpdate(row) {
      const id = (row && row.id) || this.ids[0];
      if (!id) return;
      this.reset();
      getReportDefinition(id).then((res) => {
        this.form = Object.assign({}, this.form, res.data || {});
        this.open = true;
        this.title = "修改报表定义";
      });
    },
    submitForm() {
      this.$refs.form.validate((valid) => {
        if (!valid) return;
        const request = this.form.id ? updateReportDefinition(this.form) : addReportDefinition(this.form);
        request.then(() => {
          this.$modal.msgSuccess(this.form.id ? "修改成功" : "新增成功");
          this.open = false;
          this.getList();
          this.loadAssetCenter();
        });
      });
    },
    handleDelete(row) {
      const ids = row && row.id ? [row.id] : this.ids;
      if (!ids.length) return;
      this.$modal
        .confirm(`确认删除选中的 ${ids.length} 条报表定义吗？`)
        .then(() => Promise.all(ids.map((id) => deleteReportDefinition(id))))
        .then(() => {
          this.$modal.msgSuccess("删除成功");
          this.getList();
          this.loadAssetCenter();
        })
        .catch(() => {});
    },
    useTemplate(row) {
      this.workbenchReportId = row.reportId;
      this.centerTab = "workbench";
      this.loadWorkbenchDesign();
    },
    selectWorkbenchReport(row) {
      this.workbenchReportId = row.id;
      this.publishReportId = row.id;
      this.centerTab = "workbench";
      this.loadWorkbenchDesign();
    },
    onWorkbenchReportChange() {
      this.loadWorkbenchDesign();
    },
    loadWorkbenchDesign() {
      if (!this.workbenchReportId) return;
      getReportDesign(this.workbenchReportId).then((res) => {
        const data = res.data || {};
        const fields = data.fields || [];
        const joins = data.joins || [];
        this.designForm.fields = fields.map((item) => Object.assign({}, item, { _groupSwitch: Number(item.isGroupDim || 0) === 1 }));
        this.designForm.joins = joins;
        this.designForm.customSql = data.customSql || "";
        this.designMainTable = (fields.find((item) => item.sourceTable) || {}).sourceTable || "";
        this.primeUsedTableColumns();
      });
    },
    saveWorkbenchDesign() {
      if (!this.workbenchReportId) {
        this.$modal.msgWarning("请先选择报表");
        return;
      }
      const payload = {
        fields: (this.designForm.fields || []).map((item, idx) => ({
          ...item,
          valueType: (item.valueType || "").trim() || "STRING",
          displayOrder: item.displayOrder === undefined ? idx : item.displayOrder,
          isEnabled: item.isEnabled === undefined ? 1 : item.isEnabled,
          isGroupDim: item._groupSwitch ? 1 : Number(item.isGroupDim || 0)
        })),
        joins: this.designForm.joins || [],
        customSql: this.designForm.customSql || "",
        aggregatePolicy: null
      };
      payload.fields.forEach((item) => delete item._groupSwitch);
      saveReportDesign(this.workbenchReportId, payload).then(() => {
        this.$modal.msgSuccess("工作台设计保存成功");
      });
    },
    handlePreviewWorkbench() {
      if (!this.workbenchReportId) {
        this.$modal.msgWarning("请先选择报表");
        return;
      }
      previewReportRuntime(this.workbenchReportId, {
        pageNum: 1,
        pageSize: 10,
        filters: [],
        sorts: []
      }).then((res) => {
        this.previewData = res.data || { dataSourceMode: "", total: 0, rows: [], generatedSql: "" };
      });
    },
    runPublishChecks() {
      if (!this.publishReportId) {
        this.$modal.msgWarning("请先选择目标报表");
        return;
      }
      previewReportRuntime(this.publishReportId, {
        pageNum: 1,
        pageSize: 10,
        filters: [],
        sorts: []
      }).then((res) => {
        const data = res.data || {};
        const sql = (data.generatedSql || "").trim();
        const rows = data.rows || [];
        this.publishChecks.sqlSafe = sql.length > 0 && sql.toUpperCase().startsWith("SELECT");
        this.publishChecks.previewOk = rows.length > 0;
        this.publishChecks.menuHint = true;
        this.publishTip = this.publishChecks.previewOk
          ? "检查完成：可发布。发布后将自动执行菜单与权限同步。"
          : "检查完成：预览结果为空，请确认业务数据与筛选条件后再发布。";
      });
    },
    publishSelected() {
      if (!this.publishReportId) {
        this.$modal.msgWarning("请先选择目标报表");
        return;
      }
      const row = this.list.find((item) => item.id === this.publishReportId);
      if (!row) {
        this.$modal.msgWarning("目标报表不存在，请刷新后重试");
        return;
      }
      this.handlePublish(row);
    },
    handlePublish(row) {
      this.$modal
        .confirm(`确认发布报表【${row.reportName}】吗？`)
        .then(() => publishReportDefinition(row.id))
        .then(() => {
          this.publishTip = "发布成功。若左侧菜单未立即出现，可使用菜单诊断/补建。";
          this.$modal.msgSuccess("发布成功");
          this.getList();
        })
        .catch(() => {});
    },
    diagnoseSelectedMenu() {
      if (!this.publishReportId) {
        this.$modal.msgWarning("请先选择目标报表");
        return;
      }
      menuDiagnosticByReportId(this.publishReportId).then((res) => {
        this.$modal.msgSuccess((res && res.msg) || "菜单诊断完成");
      });
    },
    handleRebuildMenus() {
      this.$modal
        .confirm("确认对所有已发布报表重建菜单吗？")
        .then(() => rebuildPublishedReportMenus())
        .then((res) => {
          this.$modal.msgSuccess((res && res.msg) || "菜单重建完成");
        })
        .catch(() => {});
    },
    handleAddField() {
      this.designForm.fields.push({
        fieldKey: "",
        sourceTable: this.designMainTable || "",
        sourceColumn: "",
        exprText: "",
        aggregateFn: "",
        valueType: "STRING",
        isGroupDim: 0,
        _groupSwitch: false,
        displayOrder: this.designForm.fields.length,
        isEnabled: 1
      });
    },
    handleRemoveField(index) {
      this.designForm.fields.splice(index, 1);
    },
    onGroupSwitchChange(row) {
      row.isGroupDim = row._groupSwitch ? 1 : 0;
    },
    handleAddJoin() {
      this.designForm.joins.push({
        leftTable: this.designMainTable || "",
        leftColumn: "",
        rightTable: "",
        rightColumn: "",
        joinType: "LEFT",
        extraCondition: "",
        joinOrder: this.designForm.joins.length
      });
    },
    onFieldTableChange(row) {
      row.sourceColumn = "";
      row.valueType = "STRING";
      this.ensureTableColumnsLoaded(row.sourceTable);
    },
    onFieldColumnChange(row) {
      if (!row || !row.sourceTable || !row.sourceColumn) {
        return;
      }
      const inferred = this.resolveValueTypeByColumn(row.sourceTable, row.sourceColumn);
      if (!row.valueType || row.valueType === "STRING") {
        row.valueType = inferred;
      }
    },
    onJoinLeftTableChange(row) {
      row.leftColumn = "";
      this.ensureTableColumnsLoaded(row.leftTable);
    },
    onJoinRightTableChange(row) {
      row.rightColumn = "";
      this.ensureTableColumnsLoaded(row.rightTable);
    },
    appendMainTableColumns() {
      if (!this.designMainTable) {
        this.$modal.msgWarning("请先选择主表");
        return;
      }
      this.ensureTableColumnsLoaded(this.designMainTable).then(() => {
        const columns = this.getTableColumns(this.designMainTable);
        const existing = new Set((this.designForm.fields || []).map((item) => `${item.sourceTable}.${item.sourceColumn}`));
        columns.forEach((item) => {
          const key = `${this.designMainTable}.${item.columnName}`;
          if (existing.has(key)) return;
          this.designForm.fields.push({
            fieldKey: item.columnName,
            sourceTable: this.designMainTable,
            sourceColumn: item.columnName,
            fieldAlias: item.columnComment || item.columnName,
            exprText: "",
            aggregateFn: "",
            valueType: this.mapDataTypeToValueType(item.dataType),
            isGroupDim: 0,
            _groupSwitch: false,
            displayOrder: this.designForm.fields.length,
            isEnabled: 1
          });
        });
      });
    },
    primeUsedTableColumns() {
      const tableSet = new Set();
      if (this.designMainTable) tableSet.add(this.designMainTable);
      (this.designForm.fields || []).forEach((item) => item.sourceTable && tableSet.add(item.sourceTable));
      (this.designForm.joins || []).forEach((item) => {
        item.leftTable && tableSet.add(item.leftTable);
        item.rightTable && tableSet.add(item.rightTable);
      });
      Array.from(tableSet).forEach((tableName) => this.ensureTableColumnsLoaded(tableName));
    },
    ensureTableColumnsLoaded(tableName) {
      if (!tableName || this.tableColumnsMap[tableName]) return Promise.resolve();
      return listReportMetaFields(tableName).then((res) => {
        this.$set(this.tableColumnsMap, tableName, res.data || []);
      });
    },
    getTableColumns(tableName) {
      return this.tableColumnsMap[tableName] || [];
    },
    resolveValueTypeByColumn(tableName, columnName) {
      const column = this.getTableColumns(tableName).find((item) => item.columnName === columnName);
      if (!column) {
        return "STRING";
      }
      return this.mapDataTypeToValueType(column.dataType);
    },
    mapDataTypeToValueType(dataType) {
      const type = String(dataType || "").toLowerCase();
      if (!type) return "STRING";
      if (/(int|decimal|numeric|float|double|real|bigint|smallint|mediumint|tinyint)/.test(type)) {
        return "NUMBER";
      }
      if (/(date|time|year|timestamp|datetime)/.test(type)) {
        return "DATETIME";
      }
      if (/(bool|boolean|bit)/.test(type)) {
        return "BOOLEAN";
      }
      return "STRING";
    },
    formatTableLabel(item) {
      const comment = item.tableComment ? `（${item.tableComment}）` : "";
      return `${item.tableName}${comment}`;
    },
    formatColumnLabel(item) {
      const comment = item.columnComment ? `（${item.columnComment}）` : "";
      return `${item.columnName}${comment}`;
    }
  }
};
</script>

<style scoped>
.asset-card {
  min-height: 340px;
}
</style>
