// 通用表格页面混入
import dynamicModelApi from '@/api/entity/dynamicModelApi.js';
import { mapFormFieldsToEditColumns } from '@/utils/formEditColumns.js';
import { getForeignRowLabel, rowsToIdOptions } from '@/utils/foreignRowLabel.js';
import { orderActionBtnsViewEditFirst } from '@/utils/actionBtnOrder.js';

export default {
  created() {
    this.ensure_meta_shape();
  },
  methods: {
    /** 操作列：查看、编辑排在最左侧相邻，其余按钮顺序在后 */
    renderRowActionBtns(h, btns) {
      return window.framework.uiTool.getBtn(h, orderActionBtnsViewEditFirst(btns));
    },

    field_display_name(f) {
      if (!f) return "";
      return f.label || f.title || f.key || "";
    },

    /**
     * 按 meta.formFields 整理行数据，供 editModal 绑定（InputNumber 不能接收 ""）。
     * 外键数字字段空值用 undefined；其它 number 空值或非数字用 0。
     */
    normalizeRowForEditModal(row) {
      if (!row || typeof row !== 'object') return row;
      const fields =
        this.meta && Array.isArray(this.meta.formFields) ? this.meta.formFields : [];
      if (!fields.length) return { ...row };
      const o = { ...row };
      for (const f of fields) {
        if (!f || f.form === false || f.type !== 'number') continue;
        const k = f.key;
        const v = o[k];
        if (/_id$/.test(k)) {
          if (v === '' || v === null || v === undefined) {
            o[k] = undefined;
          } else {
            const n = Number(v);
            o[k] = Number.isNaN(n) ? undefined : n;
          }
        } else {
          if (v === '' || v === null || v === undefined) {
            o[k] = 0;
          } else {
            const n = Number(v);
            o[k] = Number.isNaN(n) ? 0 : n;
          }
        }
      }
      return o;
    },

    // 兼容页面只定义 fields 的场景，统一补齐 formFields / columns
    ensure_meta_shape() {
      if (!this.meta || typeof this.meta !== 'object') {
        return;
      }

      const fields = Array.isArray(this.meta.formFields)
        ? this.meta.formFields
        : (Array.isArray(this.meta.fields) ? this.meta.fields : []);

      // code 字段：后端自动生成，表单中不显示
      fields.forEach((f) => {
        if (f && f.key === 'code') {
          f.form = false;
          f.required = false;
        }
      });

      if (!Array.isArray(this.meta.formFields)) {
        const formFields = fields.filter((f) => f && f.form !== false);
        this.$set(this.meta, 'formFields', formFields);
      }

      if (!Array.isArray(this.meta.columns)) {
        const columns = fields
          .filter((f) => f && f.list)
          .map((f) => ({
            key: f.key,
            title: f.label || f.title,
            minWidth: f.minWidth,
          }));

        this.$set(this.meta, 'columns', columns);
      }
    },

    // 通用的编辑列配置生成方法（实现见 utils/formEditColumns.js）
    generateEditColumns(formFields, selectSources) {
      return mapFormFieldsToEditColumns(formFields, selectSources);
    },

    /**
     * 标准列表列：外键列显示关联名称（select_sources）、布尔、日期等
     * meta 需含 columns，以及 fields 或 formFields（带 type）
     */
    buildListColumnsFromMeta(meta, selectSources) {
      if (!meta || !Array.isArray(meta.columns)) return [];
      const allFields = meta.fields || meta.formFields || [];
      return this.generateListColumns(meta.columns, allFields, selectSources);
    },

    // 通用的列表列配置生成方法
    generateListColumns(columns, allFields, selectSources) {
      if (!columns || !Array.isArray(columns)) return [];

      const fields = Array.isArray(allFields) ? allFields : [];

      /** 系统统一时间字段（与后端 create_time / last_modify_time 一致），排在业务列之后、操作列之前 */
      const colList = [...columns];
      const keySet = new Set(colList.map((c) => c && c.key).filter(Boolean));
      if (!keySet.has('create_time')) {
        colList.push({ key: 'create_time', title: '创建时间', minWidth: 160 });
        keySet.add('create_time');
      }
      if (!keySet.has('last_modify_time')) {
        colList.push({ key: 'last_modify_time', title: '最后修改时间', minWidth: 160 });
        keySet.add('last_modify_time');
      }

      const boolKeys = new Set(fields.filter((f) => f.type === 'bool').map((f) => f.key));
      const selectKeys = new Set(fields.filter((f) => f.type === 'select').map((f) => f.key));

      return colList.map((c) => {
        // 外键：已加载下拉数据时显示名称（含仓库/库区/巷道及 mat_sku 等）
        if (
          selectSources &&
          selectSources[c.key] &&
          Array.isArray(selectSources[c.key]) &&
          selectSources[c.key].length &&
          /_id$/.test(c.key)
        ) {
          return {
            ...c,
            render: (h, params) => {
              const id = params.row[c.key];
              const source = selectSources[c.key];
              const item = source && source.find((w) => String(w.key) === String(id));
              return h('span', item ? item.value : id != null && id !== '' ? String(id) : '-');
            },
          };
        }
        
        // 处理选择字段显示（status 按字段 source_key）
        if (selectKeys.has(c.key)) {
          const fieldDef = fields.find((f) => f.key === c.key);
          const source_key = fieldDef && fieldDef.source_key;
          return {
            ...c,
            render: (h, params) => {
              const value = params.row[c.key];
              let source;
              if (source_key && selectSources && selectSources[source_key]) {
                source = selectSources[source_key];
              } else if (c.key === 'type') {
                source = selectSources && selectSources.warehouse_type_options;
              } else if (c.key === 'tray_type_id') {
                source = selectSources && selectSources.tray_type_id;
              } else if (c.key === 'lock_type') {
                source = selectSources && selectSources.lock_type_options;
              } else if (c.key === 'status' && source_key) {
                source = selectSources && selectSources[source_key];
              } else if (c.key === 'status') {
                source = selectSources && selectSources.tray_status_options;
              } else {
                source = selectSources && selectSources.yes_no_options;
              }
              const option = source && source.find((opt) => String(opt.key) === String(value));
              return h('span', option ? option.value : value);
            },
          };
        }
        
        // 处理布尔字段显示
        if (boolKeys.has(c.key)) {
          return {
            ...c,
            render: (h, params) => {
              const v = params.row[c.key];
              const on = v === true || v === 1 || v === '1';
              return h('Tag', { props: { color: on ? 'green' : 'default' } }, on ? '是' : '否');
            },
          };
        }
        
        // 处理日期字段显示
        if (this.isDateLikeColumnKey && this.isDateLikeColumnKey(c.key)) {
          return {
            ...c,
            render: (h, params) => {
              const raw =
                c.key === 'create_time' || c.key === 'last_modify_time'
                  ? this.pickRowTimeCell(params.row, c.key)
                  : params.row[c.key];
              return h('span', this.formatCellDate(raw, c.key));
            },
          };
        }
        
        return { ...c };
      });
    },

    // 从 Vuex store (wms_dict) 获取字典选项
    getDictOptions(key) {
      if (!this.$store || !this.$store.state.wms_dict) return [];
      return this.$store.state.wms_dict[key] || [];
    },

    // 通用的数据源加载方法（从 store 读取字典，不再请求 sys_parameter）
    async loadSelectSources(formFields, idFieldToModelFn, getRowLabelFn) {
      const sources = {};

      sources.yes_no_options           = this.getDictOptions('yes_no');
      sources.warehouse_type_options   = this.getDictOptions('warehouse_type');
      sources.lock_type_options        = this.getDictOptions('lock_type');
      sources.tray_status_options      = this.getDictOptions('tray_status');
      sources.tray_type_status_options = this.getDictOptions('tray_type_status');
      sources.receiving_status_options = this.getDictOptions('receiving_status');
      sources.inbound_status_options   = this.getDictOptions('inbound_status');
      sources.send_status_options      = this.getDictOptions('send_status');
      sources.outbound_status_options  = this.getDictOptions('outbound_status');
      sources.move_status_options      = this.getDictOptions('move_status');
      sources.damage_status_options    = this.getDictOptions('damage_status');
      sources.count_status_options     = this.getDictOptions('count_status');
      sources.receiving_type_options   = this.getDictOptions('receiving_type');
      sources.send_type_options        = this.getDictOptions('send_type');
      sources.fee_charge_type_options = this.getDictOptions('fee_charge_type_options');
      sources.fee_generate_type_options = this.getDictOptions('fee_generate_type_options');
      sources.fee_collection_type_options = this.getDictOptions('fee_collection_type_options');
      sources.fee_item_inbound_options = this.getDictOptions('fee_item_inbound_options');
      sources.fee_item_outbound_options = this.getDictOptions('fee_item_outbound_options');
      sources.packaging_status_options = this.getDictOptions('packaging_status_options');

      // 加载外键数据
      const idFields = formFields
        .filter((f) => f.type === 'number' && /_id$/.test(f.key))
        .map((f) => f.key);

      for (const k of idFields) {
        const model = idFieldToModelFn(k);
        if (!model) {
          sources[k] = [];
          continue;
        }
        try {
          const res = await dynamicModelApi.all(model);
          const rows = res && res.code === 0 && res.data ? res.data : [];
          sources[k] = rowsToIdOptions(rows, getRowLabelFn || getForeignRowLabel);
        } catch (e) {
          sources[k] = [];
        }
      }

      return sources;
    },

    // 通用的空表单构建方法
    generateEmptyForm(formFields) {
      const o = {};
      if (!formFields) return o;
      
      for (const f of formFields) {
        if (f.type === 'bool') o[f.key] = false;
        else if (f.type === 'number') {
          // 外键用 Select 时，0 易被当成「已选」且无法匹配 Option，校验与展示都不直观
          o[f.key] = /_id$/.test(f.key) ? undefined : 0;
        } else if (f.type === 'select') {
          if (f.key === 'lock_type') o[f.key] = 0;
          else if (f.data_type === 'number' && /_id$/.test(f.key)) o[f.key] = undefined;
          else o[f.key] = '';
        } else o[f.key] = '';
      }
      return o;
    },

    // 通用的日期相关方法
    isDateLikeColumnKey(key) {
      if (!key) return false;
      return (
        key === 'stat_date' ||
        key === 'create_time' ||
        key === 'last_modify_time' ||
        /_time$/.test(key) ||
        /_date$/.test(key)
      );
    },

    /**
     * 列表「创建时间 / 最后修改时间」与后端 Sequelize 字段对齐：
  
     */
    pickRowTimeCell(row, key) {
      if (!row || !key) return undefined;
      if (key === 'create_time') {
        return row.create_time;
      }
      if (key === 'last_modify_time') {
        return row.last_modify_time;
      }
      return row[key];
    },

    formatCellDate(v, key) {
      if (v === null || v === undefined || v === '') return '-';
      const d = v instanceof Date ? v : new Date(v);
      if (Number.isNaN(d.getTime())) return String(v);
      const pad = (n) => String(n).padStart(2, '0');
      const y = d.getFullYear();
      const m = pad(d.getMonth() + 1);
      const day = pad(d.getDate());
      const hh = pad(d.getHours());
      const mm = pad(d.getMinutes());
      const dateOnly = key === 'stat_date' || (key && /_date$/.test(key) && !/_time$/.test(key));
      if (dateOnly) return y + '-' + m + '-' + day;
      return y + '-' + m + '-' + day + ' ' + hh + ':' + mm;
    },

    /** 外键行展示文案；实现见 @/utils/foreignRowLabel.js */
    getRowLabel(row) {
      return getForeignRowLabel(row);
    },

    // 通用的数据规范化方法
    generatePayload(raw, formFields) {
      const o = { ...raw };
      if (!formFields) return o;
      
      const typeByKey = {};
      const selectDataTypeByKey = {};
      for (const f of formFields) {
        if (!f || !f.key) continue;
        typeByKey[f.key] = f.type;
        if (f.data_type) selectDataTypeByKey[f.key] = f.data_type;
      }
      
      for (const k of Object.keys(o)) {
        const t = typeByKey[k];
        let v = o[k];
        
        if (t === 'number') {
          if (v === '' || v === null || v === undefined) { 
            o[k] = null; 
          } else { 
            const n = Number(v); 
            o[k] = Number.isNaN(n) ? v : n; 
          }
        } else if (t === 'bool') {
          o[k] = v === true || v === 1 || v === '1';
        } else if (t === 'select') {
          const numSelect = k === 'lock_type' || selectDataTypeByKey[k] === 'number';
          if (numSelect) {
            if (v === '' || v === null || v === undefined) {
              o[k] = null;
            } else {
              const n = Number(v);
              o[k] = Number.isNaN(n) ? v : n;
            }
          }
        } else if (t === 'date' || t === 'datetime') {
          if (v instanceof Date) {
            const pad = (n) => String(n).padStart(2, '0');
            if (t === 'date') {
              o[k] = v.getFullYear() + '-' + pad(v.getMonth() + 1) + '-' + pad(v.getDate());
            } else {
              o[k] = v.getFullYear() + '-' + pad(v.getMonth() + 1) + '-' + pad(v.getDate()) + 
                     ' ' + pad(v.getHours()) + ':' + pad(v.getMinutes()) + ':' + pad(v.getSeconds());
            }
          }
        }
      }
      return o;
    },

    // 通用的表单验证规则生成方法（与 iView Form / async-validator 约定一致：输入类 blur，选择类 change）
    generateEditRules(formFields) {
      if (!formFields) {
        return {};
      }

      const rules = {};
      for (const f of formFields) {
        if (f.form === false) continue;
        if (!f.required) continue;
        if (f.type === 'bool') continue;
        const fieldTitle = f.label || f.title || f.key;

        if (f.type === 'date' || f.type === 'datetime') {
          rules[f.key] = [
            { required: true, type: 'date', message: '请选择' + fieldTitle, trigger: 'change' }
          ];
          continue;
        }

        // 数字 id 用 Select 渲染（如 tenant_id：type=select + data_type=number），Option 常为字符串；
        // 仅用 async-validator required 易与 iView 绑定不一致导致「已选仍报错」
        if (f.type === 'select' && f.data_type === 'number' && /_id$/.test(f.key)) {
          rules[f.key] = [
            {
              required: true,
              trigger: 'change',
              validator(rule, value, callback) {
                const n = value === '' || value === null || value === undefined ? NaN : Number(value);
                if (Number.isNaN(n) || n === 0) {
                  callback(new Error('请选择' + fieldTitle));
                } else {
                  callback();
                }
              }
            }
          ];
          continue;
        }

        if (f.type === 'select') {
          rules[f.key] = [
            { required: true, message: '请选择' + fieldTitle, trigger: 'change' }
          ];
          continue;
        }

        // 外键：generateEditColumns 里用 Select，值为数字 id，但 Option 上可能是字符串；不能用 type:'number' 直接校验
        if (f.type === 'number' && /_id$/.test(f.key)) {
          rules[f.key] = [
            {
              required: true,
              trigger: 'change',
              validator(rule, value, callback) {
                const n = value === '' || value === null || value === undefined ? NaN : Number(value);
                if (Number.isNaN(n) || n === 0) {
                  callback(new Error('请选择' + fieldTitle));
                } else {
                  callback();
                }
              }
            }
          ];
          continue;
        }

        if (f.type === 'number') {
          rules[f.key] = [
            {
              required: true,
              type: 'number',
              message: '请填写' + fieldTitle,
              trigger: 'blur'
            }
          ];
          continue;
        }

        rules[f.key] = [{ required: true, message: '请填写' + fieldTitle, trigger: 'blur' }];
      }
      return rules;
    }
  }
};
