/**
 * 演示页 / 轻量业务列表用的表格与编辑辅助方法（原 tableMixin 能力的最小子集）。
 */
import { mapFormFieldsToEditColumns } from "@/utils/formEditColumns.js";
import { getForeignRowLabel } from "@/utils/foreignRowLabel.js";

export default {
  methods: {
    /**
     * 把表单字段配置转成「编辑弹窗 / 表单」用的列定义（含下拉选项渲染等）。
     * @param {Array} formFields 表单字段元数据
     * @param {Object} selectSources 各字段对应的 { key: [{ key, value }] } 下拉数据
     */
    generateEditColumns(formFields, selectSources) {
      return mapFormFieldsToEditColumns(formFields, selectSources);
    },

    /**
     * 根据列表展示字段生成 iView Table 的 columns；select 或 *_id 数字列用下拉文案渲染。
     * @param {Array} listFields 列表要展示的字段配置
     * @param {Array} _allFields 预留，与全量字段对齐时可扩展
     * @param {Object} selectSources 与 generateEditColumns 同源的下拉映射
     */
    generateListColumns(listFields, _allFields, selectSources) {
      if (!Array.isArray(listFields)) {
        return [];
      }
      return listFields.map((f) => {
        const col = {
          title: f.title || f.key,
          key: f.key,
          minWidth: f.minWidth || 120,
          ellipsis: true,
        };
        const useLookup =
          f.type === "select" ||
          (f.type === "number" && /_id$/.test(String(f.key)));
        if (useLookup) {
          const srcKey = f.source_key || f.key;
          col.render = (h, params) => {
            const v = params.row[f.key];
            const opts = (selectSources && selectSources[srcKey]) || [];
            const o = opts.find(
              (x) => x.key === v || String(x.key) === String(v)
            );
            return h("span", o ? o.value : v != null ? String(v) : "");
          };
        }
        return col;
      });
    },

    /**
     * 把一行记录转成人类可读的主展示文案（用于外键下拉、关联展示等）。
     * @param {Object} row 后端返回的单条记录
     */
    getRowLabel(row) {
      return getForeignRowLabel(row);
    },

    /**
     * 按字段配置批量请求 `/{model}/all`，组装成 selectSources（下拉 key/value）。
     * idFieldToModel(fieldKey) 返回的模型名为空则跳过该字段；依赖 this.$http。
     * @param {Array} fields 表单或列表字段元数据
     * @param {Function} idFieldToModel 字段 key -> 后端资源名（如 tenant_id -> sys_tenant）
     * @param {Function} _getRowLabel 预留，可传入自定义取文案函数
     */
    async loadSelectSources(fields, idFieldToModel, _getRowLabel) {
      const result = {};
      if (!Array.isArray(fields) || !this.$http) {
        return result;
      }
      for (const f of fields) {
        const model =
          typeof idFieldToModel === "function" ? idFieldToModel(f.key) : "";
        if (!model) {
          continue;
        }
        try {
          const res = await this.$http.get(`/${model}/all`, {});
          if (res && res.code === 0 && Array.isArray(res.data)) {
            const key = f.source_key || f.key;
            result[key] = res.data.map((r) => ({
              key: r.id,
              value: getForeignRowLabel(r),
            }));
          }
        } catch (e) {
          console.warn("loadSelectSources skip", f.key, e && e.message);
        }
      }
      return result;
    },

    /**
     * 根据字段上的 required 生成 iView Form 校验 rules（必填 + 失焦提示）。
     * @param {Array} fields 表单字段元数据
     */
    generateEditRules(fields) {
      const rules = {};
      if (!Array.isArray(fields)) {
        return rules;
      }
      for (const f of fields) {
        if (f.required) {
          const label = f.title || f.label || f.key;
          rules[f.key] = [
            {
              required: true,
              message: "请填写" + label,
              trigger: "blur",
            },
          ];
        }
      }
      return rules;
    },

    /**
     * 按字段类型生成一份「空表单」初始值（number 为 null，bool 为 false，其余为 ""）。
     * @param {Array} fields 表单字段元数据
     */
    generateEmptyForm(fields) {
      const form = {};
      if (!Array.isArray(fields)) {
        return form;
      }
      for (const f of fields) {
        if (f.type === "number") {
          form[f.key] = null;
        } else if (f.type === "bool") {
          form[f.key] = false;
        } else {
          form[f.key] = "";
        }
      }
      return form;
    },

    /**
     * 从原始对象中只挑出 fields 里声明过的 key，用于提交前裁剪多余字段。
     * @param {Object} raw 表单或行数据
     * @param {Array} fields 允许的字段列表
     */
    generatePayload(raw, fields) {
      const out = {};
      if (!raw || !Array.isArray(fields)) {
        return out;
      }
      for (const f of fields) {
        const k = f.key;
        if (Object.prototype.hasOwnProperty.call(raw, k)) {
          out[k] = raw[k];
        }
      }
      return out;
    },

    /**
     * 编辑弹窗打开时浅拷贝一行，避免表格行对象与表单双向绑定互相污染。
     * @param {Object} row 当前行
     */
    normalizeRowForEditModal(row) {
      return row && typeof row === "object" ? { ...row } : {};
    },

    /**
     * 表格「操作」列里渲染一组小按钮；点击会 stopPropagation，避免触发行选择。
     * @param {Function} h Vue 的 createElement
     * @param {Array<{ title, type?, click }>} items 按钮文案、样式类型、点击回调
     */
    renderRowActionBtns(h, items) {
      if (!Array.isArray(items) || !items.length) {
        return h("span", "");
      }
      return h(
        "div",
        { class: "table-row-actions" },
        items.map((item, i) =>
          h(
            "Button",
            {
              key: i,
              props: { type: item.type || "default", size: "small" },
              style: { marginRight: i < items.length - 1 ? "8px" : "0" },
              on: {
                click: (e) => {
                  if (e && e.stopPropagation) {
                    e.stopPropagation();
                  }
                  if (typeof item.click === "function") {
                    item.click();
                  }
                },
              },
            },
            item.title || ""
          )
        )
      );
    },
  },
};
