<template>
  <div class="base-msg-form">
    <LjHeader v-if="title" :title="title">
      <template #toolButton v-if="addable">
        <el-tag
          v-for="(tag, index) in dynamicTags"
          :key="'basemsgtags' + index"
          class="tag-item mr-8"
          :closable="editBaseMsgTag"
          type="info"
          :effect="tag.type == 'tag' ? 'light' : 'dark'"
          round
          :disable-transitions="true"
          @close="toDelBasemsgTags(tag)"
          @click="toLoadBasemsgTags(tag)"
        >
          {{ tag.name }}
        </el-tag>
        <template v-if="editBaseMsgTag">
          <el-input
            v-if="inputVisible"
            ref="InputTagRef"
            v-model="inputValue"
            size="small"
            style="width: 126px"
            maxlength="20"
            :placeholder="$t('business.tips.baseMsgTags.placeholder')"
            @keyup.enter="toAddBasemsgTag"
          />
          <el-button v-else class="tag-item" size="small" :icon="Plus" @click="toShowInput">{{
            $t("business.tips.baseMsgTags.new")
          }}</el-button>
        </template>
        <el-divider direction="vertical" />
        <el-button circle :icon="editBaseMsgTag ? ArrowRight : Setting" @click="editBaseMsgTag = !editBaseMsgTag"></el-button>
      </template>
    </LjHeader>
    <BaseForm
      ref="BaseFormRef"
      :columns="searchColumns"
      :search-param="addable ? searchParam : data ?? baseData"
      :search-col="searchCol"
      :layout-attr="layoutAttr"
      :layout-attr-define="layoutAttrDefine"
      @confirm="saveSearchSettingFunc"
    />
  </div>
</template>

<script setup lang="ts" name="BaseMsgForm">
import { ref, reactive, watch, computed, provide, onMounted, nextTick, toRef } from "vue";
import { Setting, ArrowRight, Plus } from "@element-plus/icons-vue";
// import { ElTable } from "element-plus";
import { useBaseMsg } from "@/hooks/useBaseMsg";
// import { useSelection } from "@/hooks/useSelection";
import { BreakPoint } from "@/components/Grid/interface";
import { ColumnProps } from "@/components/LjVxeTable/interface";
// import { Refresh, Printer, Operation, Search } from "@element-plus/icons-vue";
import { handleProp, streamlineFunc } from "@/utils";
import BaseForm from "./components/BaseForm.vue";
import LjHeader from "@/components/LjHeader/index.vue";
import { cloneDeep, pick } from "lodash-es";
import { useLayoutStore } from "@/stores/modules/layout";
import { useUserStore } from "@/stores/modules/user";
import { useI18n } from "vue-i18n";
import { useGlobalStore } from "@/stores/modules/global";
import { BaseMsgTagsGlobal } from "@/stores/interface";
import { ElMessage } from "element-plus";
import dayjs from "dayjs";
import { isNumber } from "@/utils/is";

const { t } = useI18n();
// const { prefixCls } = useDesign("base-msg-from");
const globalStore = useGlobalStore();
// const { globalAlign, globalLabelWidth } = storeToRefs(globalStore);

export interface BaseMsgProps {
  /**
   * @argument ColumnProps[] 列配置项  ==> 必传
   */
  columns: ColumnProps[];
  /**
   * @argument any 静态 table data 数据，若存在则不会使用 requestApi 返回的 data ==> 非必传
   */
  data?: any[];
  /**
   * @argument string 请求表格数据的 api ==> 非必传
   */
  requestApi?: (params: any) => Promise<any>;
  /**
   * @argument boolean 是否自动执行请求 api ==> 非必传（默认为true）
   */
  requestAuto?: boolean;
  /**
   * @argument function 表格 api 请求错误监听 ==> 非必传
   */
  requestError?: (params: any) => void;
  /**
   * @argument function 返回数据的回调函数，可以对数据进行处理 ==> 非必传
   */
  dataCallback?: (data: any) => any;
  /**
   * @argument string 基础信息标题 ==> 非必传
   */
  title?: string;
  /**
   * @argument any 初始化请求参数 ==> 非必传（默认为{}）
   */
  initParam?: any;
  /**
   * @argument boolean 是否显示表格功能按钮 ==> 非必传（默认为true）
   */
  toolButton?: boolean;
  /**
   * @argument number | Record<BreakPoint, number> 表格搜索项 每列占比配置 ==> 非必传 { xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }
   */
  searchCol?: number | Record<BreakPoint, number>;
  /**
   * @argument string 布局窗口名称
   */
  dwname?: string;
  /**
   * @argument string[] 搜索布局读取/保存时，赋值的属性
   */
  layoutAttr?: string[];
  /**
   * @argument Object 搜索默认设置，保存时移除，的属性
   */
  layoutAttrDefine?: any;
  /**
   * @argument string[] 搜索布局读取/保存时，赋值的属性
   */
  searchLayoutAttr?: string[];
  /**
   * @argument Object 搜索默认设置，保存时移除，的属性
   */
  searchLayoutAttrDefine?: any;
  /**
   * @description 是否可编辑
   */
  editable?: boolean;
  /**
   * @description 是否新增
   */
  addable?: boolean;
  /**
   * @description 验证规则 element-plus form; 可整表定义或定义在column.search.rules内
   */
  rules?: any;
  /**
   * @description 新增时,读取本地tag后执行的函数
   */
  loadTagCallback?: (data: any) => void;
}

// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<BaseMsgProps>(), {
  columns: () => [],
  requestAuto: true,
  pagination: false,
  initParam: {},
  border: true,
  toolButton: true,
  rowKey: "id",
  searchCol: () => ({ xs: 2, sm: 3, md: 4, lg: 5, xl: 5 }),
  layoutAttr: () => ["field", "title", "sortable", "order", "format", "visible", "align", "width", "fixed"],
  layoutAttrDefine: () => ({
    visible: true,
    width: 200,
    align: "center",
    sortable: false,
    order: "",
    fixed: ""
  }),
  searchLayoutAttr: () => ["order", "labelPosition", "labelWidth", "span"],
  searchLayoutAttrDefine: () => ({
    labelPosition: "top",
    labelWidth: 120,
    span: 1
  }),
  editable: false,
  rules: () => {}
});

provide("editable", props.editable);
provide("rules", props.rules);

// 布局暂存数据
const layoutStore = useLayoutStore();
const dwLayout = ref([]);
const BaseFormRef = ref<typeof BaseForm>();

// 基础信息模块 Hooks
const { baseData, searchParam, totalParam, searchInitParam, getBamseMsg } = useBaseMsg(
  props.requestApi,
  props.initParam,
  props.dataCallback
);

// 定义 enumMap 存储 enum 值（避免异步请求无法格式化单元格内容 || 无法填充搜索下拉选择）
const enumMap = ref(new Map<string, { [key: string]: any }[]>());
const baseEnumMap = ref(new Map<string, { [key: string]: any }[]>());
provide("baseMsgEnumMap", enumMap);
provide("baseFormatEnumMap", baseEnumMap);
const setEnumMap = async (col: ColumnProps) => {
  if (!col.enum) return;
  // 如果当前 enum 为后台数据需要请求数据，则调用该请求接口，并存储到 enumMap
  if (typeof col.enum !== "function") return enumMap.value.set(col.field!, col.enum!);
  const data = await col.enum();
  enumMap.value.set(col.field!, data);
};
const setBaseEnumMap = async (col: ColumnProps) => {
  if (!col.formatEnum) return;
  // 如果当前 enum 为后台数据需要请求数据，则调用该请求接口，并存储到 enumMap
  if (typeof col.formatEnum !== "function") return baseEnumMap.value.set(col.field!, col.formatEnum!);
  const { data } = await col.formatEnum();
  baseEnumMap.value.set(col.field!, data);
};

//
/**
 * @description 树形化：基础信息columns
 */
let tableColumns = ref<ColumnProps[]>(props.columns);
/**
 * @description 基础信息列表的配置项
 */
let searchColumns = ref<ColumnProps[]>([]);

/**
 * @description 扁平化：columns，用于打印、记录
 */
let flatColumns = ref<ColumnProps[]>();

// // 扁平化 初始化 columns
const flatColumnsFunc = (columns: ColumnProps[], flatArr: ColumnProps[] = []) => {
  columns.forEach(async (col: any) => {
    if (col._children?.length) flatArr.push(...flatColumnsFunc(col._children));
    flatArr.push(col);

    // 给每一项 column 添加默认属性
    col.visible = col?.visible == false ? false : props.layoutAttrDefine.visible; // true
    col.width = col.width ?? props.layoutAttrDefine.width; // 200
    col.align = col.align ?? props.layoutAttrDefine.align; // "center"
    col.sortable = col.sortable ?? props.layoutAttrDefine.sortable; // false
    col.order = col.order ?? props.layoutAttrDefine.order; // ""
    col.fixed = col.fixed ?? props.layoutAttrDefine.fixed; // ""
    // col.isFilterEnum = col.isFilterEnum ?? true;

    // 读取个性设置属性
    if (dwFieldMap.size) {
      let userStyle = dwFieldMap.get(col.field);
      if (userStyle) {
        for (let prop of props.layoutAttr) {
          if (userStyle.hasOwnProperty(prop) && prop != "title") {
            col[prop] = userStyle[prop];
          }
        }
        col.colorder = userStyle.colorder;
        if (userStyle.search && col.search) {
          col.search.order = userStyle.search.order ?? undefined;
          col.search.span = userStyle.search.span ?? undefined;
          col.search.labelPosition = userStyle.search.labelPosition ?? undefined;
          col.search.labelWidth = userStyle.search.labelWidth ?? undefined;
        }
      }
    }

    if (["selection", "seq", "expand"].includes(col.type!)) {
    } else if (col.field == "operation") {
      col.title = t(`table.${col.field}`);
    } else {
      col.title = t(`table.${col.table}.${col.field}`);
    }

    // 搜索栏，读取个性设置属性
    if (col.search) {
      col.search.labelPosition = col.search.labelPosition ?? props.searchLayoutAttrDefine.labelPosition; // "top"
      col.search.labelWidth = col.search.labelWidth ?? props.searchLayoutAttrDefine.labelWidth; // 120
      col.search.span = col.search.span ?? props.searchLayoutAttrDefine.span; // 1
    }

    // 设置 enumMap
    setEnumMap(col);
    // 设置 表格基础信息-format枚举
    setBaseEnumMap(col);
  });

  // 读取个性设置后，排序，
  if (dwFieldMap.size) {
    flatArr.sort((a, b) => {
      return a.colorder! - b.colorder!;
    });
  }
  return flatArr.filter(item => !item._children?.length);
};

// 读取个性布局,用Map()储存
const dwFieldMap = new Map();
const loadDwLayoutFunc = (loadLayout: ColumnProps[] = []) => {
  console.log("loadLayout.value :>> ", loadLayout);
  if (!loadLayout || !loadLayout.length) return false;

  // 个性布局加顺序号
  for (const i in loadLayout) {
    loadLayout[i].colorder = Number(i);
  }

  // 个性布局构建键值Map()
  dwFieldMap.clear();
  for (const item of loadLayout) {
    dwFieldMap.set(item.field, item);
  }
  console.log("dwFieldMap :>> ", dwFieldMap);
};

const columnStreamlineFunc = (column: any, searchColumns: any) => {
  let saveCol = streamlineFunc(column, props.layoutAttr, props.layoutAttrDefine);

  // 简化搜索储存字段，以props.searchLayoutAttr为标准
  let searchMap = new Map();
  for (let item of searchColumns) {
    let saveProp = cloneDeep(props.searchLayoutAttr);
    if (item.search) {
      for (let key in props.searchLayoutAttrDefine) {
        if (item.search.hasOwnProperty(key) && props.searchLayoutAttrDefine[key] === item.search[key]) {
          saveProp.splice(saveProp.indexOf(key), 1);
        }
      }
      searchMap.set(item.field, pick(item.search, saveProp));
    }
  }

  // 合并
  if (searchMap.size) {
    for (let item of saveCol) {
      let _map = searchMap.get(item.field);
      if (_map) {
        item.search = _map;
      }
    }
  }
  console.log("settingConfirm saveCol :>> ", saveCol);
  return saveCol;
};

// 搜索栏，布局保存
const saveSearchSettingFunc = (columns: any) => {
  searchColumns.value = columns;
  // 精简当前布局
  let saveCol = columnStreamlineFunc(tableColumns.value, searchColumns.value);
  // let saveCol = streamlineFunc(columns, props.layoutAttr, props.layoutAttrDefine);

  // 保存布局
  props.dwname && layoutStore.setDwLayout(props.dwname, saveCol, t);
};

const editBaseMsgTag = ref(false);
const inputValue = ref("");
const dynamicTags = ref<BaseMsgTagsGlobal.baseMsgTagsItem[]>([]);
const inputVisible = ref(false);
const InputTagRef = ref();

/**
 * 时间格式转义, detaTime to Diff
 * @param data {value:Object}
 * @returns {Object}
 */
const getDiffToDate = (data: any) => {
  const today = dayjs(dayjs().format("YYYY-MM-DD"));
  for (const key in data) {
    if (key.indexOf("date") > -1 && isNumber(data[key])) {
      data[key] = today.add(data[key], "day").format("YYYY-MM-DD HH:mm:ss");
    }
  }
  console.log("getDiffToDate data :>> ", data);
  return data;
};

/**
 * 时间格式转义, Diff to DetaTime
 * @param data {value:Object}
 * @returns
 */
const setDateToDiff = (data: any) => {
  const today = dayjs(dayjs().format("YYYY-MM-DD"));
  for (const key in data) {
    if (key.indexOf("date") > -1) {
      let newDate = dayjs(dayjs(data[key]).format("YYYY-MM-DD"));
      data[key] = newDate.diff(today, "day");
    }
  }
  console.log("setDateToDiff data :>> ", data);
  return data;
};

const toLoadBasemsgTags = (tag: BaseMsgTagsGlobal.baseMsgTagsItem) => {
  console.log("tag :>> ", tag);
  searchParam.value = toRef(getDiffToDate(cloneDeep(tag.value)));
  console.log("searchParam.valu :>> ", searchParam.value);
};

const toShowInput = () => {
  inputVisible.value = true;
  nextTick(() => {
    InputTagRef.value!.input!.focus();
  });
};

const addTagsFunc = (list: any) => {
  let _globalTag = globalStore.baseMsgTags;
  let _idx = _globalTag.findIndex((item: any) => item.dwname === props.dwname);
  if (_idx == -1) {
    _globalTag.push({
      dwname: props.dwname,
      list: list
    });
  } else {
    _globalTag[_idx].list = list;
  }
  globalStore.setGlobalState("baseMsgTags", _globalTag);
};

/**
 * @description 新增"上次"添加记录
 */
const toAddDefaultTag = (data: any) => {
  let _tag: BaseMsgTagsGlobal.baseMsgTagsItem = {
    id: 0,
    name: t("sys.login.lastTime"),
    type: "default",
    value: setDateToDiff(cloneDeep(data))
  };

  let _dynamicTags = dynamicTags.value;
  let _delIdx = _dynamicTags.findIndex((item: any) => item.id === 0);
  if (_delIdx > -1) {
    _dynamicTags.splice(_delIdx, 1);
  }
  _dynamicTags.unshift(_tag);

  console.log("_dynamicTags :>> ", _dynamicTags);

  addTagsFunc(_dynamicTags);
};

const toAddBasemsgTag = () => {
  if (!inputValue.value) {
    // ElMessage.warning(t("business.tips.baseMsgTags.baseMsgTagNameEmpty"));
    inputVisible.value = false;
    inputValue.value = "";
    return;
  }
  let maxId = 0;
  for (const item of dynamicTags.value) {
    maxId = Math.max(maxId, item.id ?? 0);
  }
  maxId++;
  dynamicTags.value.push({
    id: maxId,
    name: inputValue.value,
    type: "tag",
    value: setDateToDiff(cloneDeep(searchParam.value))
  });
  console.log("dynamicTags.value :>> ", dynamicTags.value);

  addTagsFunc(dynamicTags.value);

  ElMessage.success(t("business.tips.baseMsgTags.success"));
  inputVisible.value = false;
  inputValue.value = "";
};

const toDelBasemsgTags = (tag: BaseMsgTagsGlobal.baseMsgTagsItem) => {
  let delIndex = dynamicTags.value.findIndex((item: any) => item.id === tag.id);
  dynamicTags.value.splice(delIndex, 1);

  let _globalTag = globalStore.baseMsgTags;
  let _idx = _globalTag.findIndex((item: any) => item.dwname === props.dwname);
  if (_idx > -1) {
    _globalTag[_idx].list = dynamicTags.value;
  }
  globalStore.setGlobalState("baseMsgTags", _globalTag);
};

const getBaseMsgTags = () => {
  // 读取本地自动补全记录
  let _globalTag = globalStore.baseMsgTags;
  console.log("_globalTag :>> ", _globalTag);
  let tagList = _globalTag.find((item: any) => item.dwname === props.dwname);
  if (tagList) {
    dynamicTags.value = tagList.list ?? [];
  }

  // 新增时,自动读取
  let idx = dynamicTags.value.findIndex((item: any) => item.id === 0);
  if (props.addable && idx > -1) {
    let data = dynamicTags.value[idx].value;
    props.loadTagCallback && (data = props.loadTagCallback(data));
    searchParam.value = toRef(getDiffToDate(data));
  }
};

// 初始化请求
onMounted(async () => {
  if (props.dwname) {
    console.log("await layoutStore.getDwLayout(props.dwname) :>> ", await layoutStore.getDwLayout(props.dwname));
    let layout = await layoutStore.getDwLayout(props.dwname);
    console.log("layout :>> ", layout);
    if (layout?.hasOwnProperty("itemvalue") && layout.itemvalue) {
      typeof layout.itemvalue == "string" && (layout.itemvalue = JSON.parse(layout.itemvalue.replace(/'/g, '"')));
      dwLayout.value = layout.itemvalue;
    }
    console.log("onMounted dwLayout.value :>> ", dwLayout.value);
    loadDwLayoutFunc(dwLayout.value);
    console.log("数行化BF，还原个性设置 tableColumns.value :>> ", tableColumns.value);
    // 扁平化，并读取个性设置
    flatColumns.value = flatColumnsFunc(tableColumns.value);
    console.log("读取个性设置 flatColumns.value :>> ", flatColumns.value);
    // 数行化，还原个性设置
    // tableColumns.value = restoreColumnsFunc(flatColumns.value);
    // tableRef.value?.reloadColumn(tableColumns.value);
    // console.log("数行化，还原个性设置 tableColumns.value :>> ", tableColumns.value);
  } else {
    flatColumns.value = flatColumnsFunc(tableColumns.value);
  }
  // colSetting = cloneDeep(flatColumns.value).filter(
  //   (item: any) => !["selection", "seq", "expand"].includes(item.type!) && item.field !== "operation"
  // );

  // // tableRef.value?.reloadColumn(tableColumns.value);
  // nextTick(() => {
  //   isUpdate.value = !isUpdate.value;
  // });

  // 过滤需要搜索的配置项
  searchColumns.value = flatColumns.value.filter(item => item.search?.el || item.search?.render);

  // // 读取缓存搜索记录
  let queryHabit = {};
  if (props.dwname) {
    const userStore = useUserStore();
    queryHabit = userStore.getQueryHabit(props.dwname);
  }

  // 设置搜索表单排序默认值 && 设置搜索表单项的默认值
  searchColumns.value.forEach((column, index) => {
    column.search!.order = column.search!.order ?? index + 2;
    if (column.search?.defaultValue !== undefined && column.search?.defaultValue !== null) {
      searchInitParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
      searchParam.value[column.search.key ?? handleProp(column.field!)] = column.search?.defaultValue;
    }
    column.rules = column.search?.rules ?? undefined;
  });
  // // 表格搜索栏,设置缓存搜索信息
  // Object.assign(searchParam.value, queryHabit);
  // 第一次搜索带入参数
  totalParam.value = searchParam.value;

  // 排序搜索表单项
  searchColumns.value.sort((a, b) => a.search!.order! - b.search!.order!);
  console.log("searchColumns.value :>> ", searchColumns.value);
  console.log("searchParam.value :>> ", searchParam.value);

  props.requestAuto && getBamseMsg();

  // 获取基础信息的本地快捷录入记录
  props.dwname && getBaseMsgTags();
});

// 监听页面 initParam 改化，重新获取基础信息数据
watch(() => props.initParam, getBamseMsg, { deep: true });

// 暴露给父组件的参数和方法(外部需要什么，都可以从这里暴露出去)
defineExpose({
  element: BaseFormRef,
  baseData,
  searchParam,
  toAddDefaultTag
});
</script>

<style lang="scss" scoped>
.base-msg-form {
  .tag-item {
    cursor: pointer;
    @include text-style-body-code;
    // padding: $space-a1 / 2 $space-b1;

    // .el-tag__close {
    //   display: none;
    // }
    // &:hover {
    //   .el-tag__close {
    //     display: block;
    //   }
    // }
  }
}
</style>
