import { VNode, ComponentPublicInstance } from "vue";
import { BreakPoint, Responsive } from "@/components/Grid/interface";
// import { TableColumnCtx } from "element-plus/es/components/table/src/table-column/defaults";
import LjVxeTable from "@/components/LjVxeTable/index.vue";
import type { VxeColumnProps, VxeTablePropTypes } from "vxe-table";
import { cloneDeep } from "lodash-es";
import dayjs from "dayjs";

export interface EnumProps {
  label?: string; // 选项框显示的文字
  value?: string | number | boolean | any[]; // 选项框值
  disabled?: boolean; // 是否禁用此选项
  tagType?: string; // 当 tag 为 true 时，此选择会指定 tag 显示类型
  children?: EnumProps[]; // 为树形选择时，可以通过 children 属性指定子选项
  [key: string]: any;
}

export type TypeProps = "index" | "checkbox" | "expand";

export type TypeFormat =
  | "yyyy-MM-dd"
  | "yyyy-MM-dd HH:mm:ss"
  | "yyyy-MM-dd HH:mm"
  | "MM/dd/yyyy"
  | "MM/dd"
  | "dd/MM/yyyy"
  | "yyyy/MM/dd"
  | "intNumber"
  | "cutNumber"
  | "cutNumber3"
  | "amountNumber"
  | "fixedNumber"
  | "percent";

export type SearchType =
  | "text"
  | "input"
  | "input-number"
  | "select"
  | "select-v2"
  | "tree-select"
  | "cascader"
  | "date-picker"
  | "time-picker"
  | "time-select"
  | "switch"
  | "slider"
  | "checkbox"
  | "checkbox-group"
  | "radio-group"
  | "autocomplete";

export type SearchRenderScope = {
  searchParam: { [key: string]: any };
  placeholder: string;
  clearable: boolean;
  options: EnumProps[];
  data: EnumProps[];
  status?: any;
};

/**
 * @description 数据模型：搜索模块
 */
export type SearchProps = {
  /**
   * @argument SearchType 当前项搜索框的类型
   */
  el?: SearchType;
  /**
   * @argument 搜索项参数，根据 element plus 官方文档来传递，该属性所有值会透传到组件，包括事件
   */
  props?: any;
  key?: string; // 当搜索项 key 不为 prop 属性时，可通过 key 指定
  order?: number; // 搜索项排序（从大到小）
  /**
   * @argument number 所占用的列数，默认为1列
   */
  span?: number;
  /**
   * @argument number 搜索字段左侧偏移列数
   */
  offset?: number;
  /**
   * @argument 搜索项默认值
   */
  defaultValue?: string | number | boolean | any[];
  /**
   * @argument 自定义搜索内容渲染（tsx语法）用于渲染搜索，或basicinfoProps详情页编辑
   */
  render?: (scope: SearchRenderScope) => VNode;
  /**
   * @argument string 表单域标签的位置
   */
  labelPosition?: "left" | "right" | "top";
  /**
   * @argument string 标签宽度
   */
  labelWidth?: string | number;
  /**
   * @description 是否隐藏标签，默认：false
   */
  labelHidden?: boolean;
  /**
   * @description 是否可视, 默认：true, false:禁止渲染详情页模式中的单元格
   */
  visible?: boolean;
  /**
   * 搜索列标题field
   */
  titleKey?: string;
  [key: string]: any;
} & Partial<Record<BreakPoint, Responsive>>;

/**
 * @description 数据模型：基础信息模块
 */
export interface basicinfoProps extends SearchProps {
  /**
   * @description 是否可编辑, 默认不限制，new：新建，edit：修改
   */
  editable?: string[] | undefined | ((params?: any) => boolean);
  /**
   * @description 编辑时，按需显隐
   */
  editvisible?: (params?: any) => boolean;
  /**
   * @argument string 分组名称
   */
  group?: string;
  /**
   * @description 扩展显示字段, 待开发
   */
  extendsField?: string[];
  /**
   * @description 是否隐藏字段, 默认：false
   */
  ishidden?: boolean;
  disabledTextCallBack?: (data: any) => string; // 禁用按钮文字回调
  /**
   * @argument boolean 编辑时form item验证规则
   */
  rules?: any;
  /**
   * @argument number 占用的行数，默认为1列
   */
  row?: number;
}

export type FieldNamesProps = {
  label: string;
  value: string;
  children?: string;
};

export type RenderScope<T> = {
  row: T;
  $index: number;
  column: VxeColumnProps<T>;
  [key: string]: any;
};

export type HeaderRenderScope<T> = {
  $index: number;
  column: VxeColumnProps<T>;
  [key: string]: any;
};

export interface ColumnProps<T = any> extends Partial<Omit<VxeColumnProps<T>, "children" | "renderCell" | "renderHeader">> {
  /**
   * @argument boolean 是否是标签展示
   */
  tag?: boolean;
  // /**
  //  * @argument boolean 是否隐藏在表格当中
  //  */
  // invisible?: boolean;
  /**
   * @argument object 列表页：搜索栏
   */
  search?: SearchProps | undefined;
  /**
   * @argument object 详情页：基础信息
   */
  basicinfo?: basicinfoProps | undefined;
  /**
   * @description search，筛选时，枚举类型（字典）
   */
  enum?: EnumProps[] | ((params?: any) => Promise<any>);
  /**
   * @description 过滤枚举
   */
  enumFilter?: (params: any, enumdata?: any, field?: string, orderStatus?: string) => EnumProps[];
  isFilterEnum?: boolean; // 当前单元格值是否根据 enum 格式化（示例：enum 只作为搜索项数据）
  fieldNames?: FieldNamesProps; // enum 指定 label && value && children 的 key 值
  headerRender?: (scope: HeaderRenderScope<T>) => VNode; // 自定义表头内容渲染（tsx语法）
  /**
   * @description 自定义单元格内容渲染（tsx语法）- 用于表格展示/详情页浏览
   */
  render?: (scope: RenderScope<T>, enumdata?: any, field?: string) => VNode | string;
  _children?: ColumnProps<T>[]; // 多级表头
  /**
   * @argument string[] 父级列表
   */
  parents?: string[];
  /**
   * @argument boolean 是否隐藏父级表头
   */
  parentHidden?: boolean;
  /**
   * @argument number 排序
   */
  order?: VxeTablePropTypes.SortOrder;
  /**
   * @argument number 排序时间,比较先后顺序
   */
  sortTime?: number;
  /**
   * @argument number 列顺序
   */
  colorder?: number;
  /**
   * @argument 所属表格，通过i18n引导的标题title
   */
  table?: string;
  // /**
  //  * @argument string 字段类型, number, date, string，默认string，可根据field名称取值”date"
  //  */
  // fieldType?: string;
  /**
   * @argument string 辅助信息：数据来源，备注信息
   */
  dataSources?: string;
  /**
   * @argument TypeFormat 辅助信息：格式函数名
   * | "yyyy-MM-dd"
   * | "yyyy-MM-dd HH:mm:ss"
   * | "yyyy-MM-dd HH:mm"
   * | "MM/dd/yyyy"
   * | "MM/dd"
   * | "dd/MM/yyyy"
   * | "yyyy/MM/dd"
   * | "cutNumber" 向下舍入,默认两位数
   * | "amountNumber" 四舍五入金额，每隔3位逗号分隔，默认2位数
   * | "fixedNumber" 四舍五入,默认两位数
   *
   */
  format?: TypeFormat;
  /**
   * @argument string 辅助信息：格式化，枚举类型（字典）
   */
  formatEnum?: selectOption[] | ((params?: any) => Promise<any>);
  /**
   * @argument boolean form item验证规则
   */
  rules?: any;
  /**
   * @augments boolean 是否限制显示
   */
  limited?: boolean | ((params?: any) => boolean);
  /**
   * @augments string 数据类型，用于赋值特殊字段的属性特征
   */
  datatype?: string;
  /**
   * @description 只对 tree-config 配置时有效，指定为树节点
   */
  treeNode?: boolean;
  /**
   * @description 自定义单元格内容渲染（tsx语法）- 用于表格编辑
   */
  editColRender?: (scope: RenderScope<T>, enumdata?: any, field?: string) => VNode | string;
  [key: string]: any;
}

/**
 * @description vxeTable组件api
 */
export type aboutVxetableApiProps = {
  /**
   * @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 boolean 是否需要分页组件 ==> 非必传（默认为true）
   */
  pagination?: boolean;
  pageSizes?: number[] | undefined;
  /**
   * @argument any 初始化请求参数 ==> 非必传（默认为{}）
   */
  initParam?: any;
  /**
   * @argument string 布局窗口名称
   */
  dwname?: string;
  /**
   * @argument string[] 布局读取/保存时，赋值的属性名称; 支持单属名称、属性路径: ["search", "search.order"]
   */
  layoutAttr?: string[];
  /**
   * @argument Object 布局默认设置，保存时移除，默认的属性；包含search、basicinfo属性的默认值
   */
  layoutAttrDefine?: any;
  /**
   * @augments boolean 是否自动加载布局, 默认true；决定是否读取通用接口返回的布局
   */
  autoLoadLayout?: boolean;
  /**
   * @argument Array 打印前,事件检查
   */
  beforePrintCallback?: (data: any) => any;
  /**
   * @argument Array 打印前,获取打印数据
   */
  printDataCallback?: (data: any) => any;
  importApi?: (params: any) => Promise<any>;
  /**
   * @description 表格/详情页，是否可编辑
   */
  editable?: boolean;
};

/**
 * @description 表格组件props
 */
export interface LjVxetableProps extends aboutVxetableApiProps {
  // /**
  //  * @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 boolean 是否需要分页组件 ==> 非必传（默认为true）
  //  */
  // pagination?: boolean;
  // pageSizes?: number[] | undefined;
  // /**
  //  * @argument any 初始化请求参数 ==> 非必传（默认为{}）
  //  */
  // initParam?: any;
  /**
   * @argument string 表格标题，目前只在打印的时候用到 ==> 非必传
   */
  title?: string; //
  /**
   * @argument boolean 是否带有纵向边框 ==> 非必传（默认为true） default（默认）, full（完整边框）, outer（外边框）, inner（内边框）, none（无边框）
   */
  border?: VxeTablePropTypes.Border;
  // /**
  //  * @argument boolean 是否显示表格功能按钮 ==> 非必传（默认为true）
  //  */
  // toolButton?: boolean;
  /**
   * @argument string 行数据的 Key，用来优化 Table 的渲染，当表格数据多选时，所指定的 id ==> 非必传（默认为 id）
   */
  rowKey?: string;
  /**
   * @argument number | Record<BreakPoint, number> 表格搜索项 每列占比配置 ==> 非必传 { xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }
   */
  searchCol?: number | Record<BreakPoint, number>;
  // /**
  //  * @argument number | Record<BreakPoint, number> 表格设置项 每列占比配置 ==> 非必传 { xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }
  //  */
  // settingCol?: number | Record<BreakPoint, number>;
  // /**
  //  * @argument string 布局窗口名称
  //  */
  // dwname?: string;
  // /**
  //  * @argument string[] 布局读取/保存时，赋值的属性名称; 支持单属名称、属性路径: ["search", "search.order"]
  //  */
  // layoutAttr?: string[];
  // /**
  //  * @argument Object 布局默认设置，保存时移除，默认的属性；包含search、basicinfo属性的默认值
  //  */
  // layoutAttrDefine?: any;
  // /**
  //  * @argument string[] 搜索布局读取/保存时，赋值的属性名称
  //  */
  // searchLayoutAttr?: string[];
  // /**
  //  * @argument Object 搜索默认设置，保存时移除，默认的属性
  //  */
  // searchLayoutAttrDefine?: any;
  /**
   * 表尾
   * @argument data
   */
  footerMethod?: (data: any) => any | boolean;
  tableCls?: string;
  /**
   * @argument 继承 vxetable props: https://vxetable.cn/#/table/api
   */
  tableProps?: any;
  /**
   * @argument 外置loading
   */
  extraLoading?: boolean | undefined;
  /**
   * 给表头的单元格附加 className https://vxetable.cn/#/table/api?filterName=header-cell-class-name
   * @argument params column
   */
  headerCellClassName?: (params: any) => any;
  /**
   * 给表头的单元格附加 className https://vxetable.cn/#/table/api?filterName=header-cell-class-name
   * @argument params column
   */
  cellClassName?: (params: any, editable: boolean) => any;
  /**
   * @argument Object 表格绑定的事件
   */
  tableEvents?: any;
  /**
   * @argument Array 表格按钮
   * @enum "refresh": 刷新, "setting": 设置, "search": 搜索栏, "location": 定位, "guide": 指导
   */
  toolButton?: string[];
  /**
   * @argument Array 表格按钮权限
   * @attention 按钮权限，需要与按钮位置对应，若无/0，则默认显示
   */
  toolButtonPower?: number[];
  // /**
  //  * @argument Array 打印前,事件检查
  //  */
  // beforePrintCallback?: (data: any) => any;
  // /**
  //  * @argument Array 打印前,获取打印数据
  //  */
  // printDataCallback?: (data: any) => any;
  /**
   * @argument boolean 折叠表格菜单按钮
   */
  collapseButtons?: boolean;
  /**
   * @description 表格搜索栏是否开启mini模式，即嵌套在slots[tableHeader]里面
   */
  miniSearchbar?: boolean;
  /**
   * @description 翻页后回调函数
   */
  pageChangeCallBack?: () => void;
  /**
   * @description 底部合计字段
   */
  footerSumAttrs?: string[];
  /**
   * @description 搜索栏按钮需要缩小尺寸的屏幕尺寸，eg: ["xs", "sm"]
   */
  searchBtnSizeExtent?: string[];

  /**
   * @description 绑定多选的列名
   */
  multiSelect?: string;
  /**
   * @description 列表是否显示搜索栏
   */
  ifSearch?: boolean;
  /**
   * @description 列表刷新后，自动选中第一行
   */
  autoSelectFirstAfterRefresh?: boolean;
  /**
   * @description 是否需要加载查询习惯
   */
  ifLoadQueryHabit?: boolean;
  /**
   * @description 当前行是否禁止点击
   */
  lockRow?: boolean | ((params: any) => boolean);
}

export type LjVxeTableInstance = Omit<InstanceType<typeof LjVxeTable>, keyof ComponentPublicInstance | keyof LjVxetableProps>;

/**
 * @description ElementPlus selecet option interface
 */
export interface selectOption {
  /**
   * @argument string 名称
   */
  label?: string;
  /**
   * @argument string 值
   */
  value: string;
  /**
   * @argument boolean 是否禁用该选项
   */
  disabled?: boolean;
}

/**
 * @description 表格过滤器条件枚举
 */
enum fModeEnum {
  /**
   * @description 包含
   */
  LIKE = "like",
  /**
   * @description 不包含
   */
  NOTLIKE = "notlike",
  /**
   * @description 等于
   */
  EQUAL = "equal",
  /**
   * @description 不等于
   */
  NE = "ne",
  /**
   * @description 大于
   */
  GREATER = "greater",
  /**
   * @description 大于等于
   */
  GE = "ge",
  /**
   * @description 小于
   */
  LESS = "less",
  /**
   * @description 小于等于
   */
  LE = "le"
}

export const hasValFunc = (target: any, val: any, fMode: string) => {
  let _t = Number(target);
  let _v = Number(val);
  let _target = isNaN(_t) ? target.toLowerCase() : target.toString();
  let _val = isNaN(_t) ? val.toLowerCase() : val.toString();
  switch (fMode) {
    case fModeEnum.LIKE: // 包含
      // console.log("_target :>> ", _target);
      // console.log("_val :>> ", _val);
      // console.log("_target.indexOf(_val) :>> ", _target.indexOf(_val));
      return _target.indexOf(_val) > -1;
    case fModeEnum.NOTLIKE: // 不包含
      return _target.indexOf(_val) == -1;
    case fModeEnum.EQUAL: // 等于
      return _target == _val;
    case fModeEnum.NE: // 不等于
      return _target != _val;
    case fModeEnum.GREATER: // 大于
      if (isNaN(_t) || isNaN(_v)) {
        return _target > _val;
      } else {
        return _t > _v;
      }
    case fModeEnum.GE: // 大于等于
      if (isNaN(_t) || isNaN(_v)) {
        return _target >= _val;
      } else {
        return _t >= _v;
      }
    case fModeEnum.LESS: // 小于
      if (isNaN(_t) || isNaN(_v)) {
        return _target < _val;
      } else {
        return _t < _v;
      }
    case fModeEnum.LE: // 小于等于
      if (isNaN(_t) || isNaN(_v)) {
        return _target <= _val;
      } else {
        return _t <= _v;
      }
  }
  return _target.indexOf(_val) > -1;
};

export const compareInputFunc = (target: any, val: any, fMode: string) => {
  let _val = val.replace("，", ",");
  if (_val.toString().indexOf(",") > -1) {
    let arr = _val.split(",");
    return arr.some((v: any) => hasValFunc(target, v, fMode));
  } else {
    return hasValFunc(target, _val, fMode);
  }
};

/**
 * @description 时间比较
 * @param format 日期格式
 * @param fMode 过滤器条件
 * @param val 值
 */
export const dataCompareFunc = (target: any, val: any, fMode: string, format: string) => {
  let _val = dayjs(dayjs(val).format(format));
  let _target = dayjs(dayjs(target).format(format));
  let diffType: any = "day";
  if (format == "YYYY-MM-DD HH:mm") {
    diffType = "minute";
  }

  switch (fMode) {
    case fModeEnum.EQUAL: // 等于
      return _target.diff(_val, diffType) == 0;
    case fModeEnum.NE: // 不等于
      return _target.diff(_val, diffType) != 0;
    case fModeEnum.GREATER: // 大于
      return _target.diff(_val, diffType) > 0;
    case fModeEnum.GE: // 大于等于
      return _target.diff(_val, diffType) >= 0;
    case fModeEnum.LESS: // 小于
      return _target.diff(_val, diffType) < 0;
    case fModeEnum.LE: // 小于等于
      return _target.diff(_val, diffType) <= 0;
  }
};

// filter default
const defaultFilter = [{ data: { vals: [], sVal: "", fMenu: "", f1Type: "", f1Val: "", fMode: "like", f2Type: "", f2Val: "" } }];

/**
 * @description 赋予特殊原始默认值
 * 正则表达式匹配，特征"$"和”^“
 * @param $ 以...结尾
 * @param ^ 以...开头
 */
const defineColumnStyle: any = {
  date: {
    fMode: fModeEnum.EQUAL
  },
  datetime: {
    fMode: fModeEnum.EQUAL
  },
  checkbox: {
    // width: 80
  },
  number: {
    fMode: fModeEnum.EQUAL
  },
  date$: {
    fMode: fModeEnum.EQUAL
  },
  time$: {
    fMode: fModeEnum.EQUAL
  },
  amt$: {
    fMode: fModeEnum.GE
  },
  qty$: {
    fMode: fModeEnum.GE
  },
  "^qty": {
    fMode: fModeEnum.GE
  },
  price$: {
    fMode: fModeEnum.GE
  }
};

export const getDefaultFilter = (item: any) => {
  let _define: any = {};
  let _defaultFilter = cloneDeep(defaultFilter);
  if (item.hasOwnProperty("datatype")) {
    _define = cloneDeep(defineColumnStyle[item.datatype]);
  } else {
    for (const key in defineColumnStyle) {
      if (key.indexOf("$") > -1 || key.indexOf("^") > -1) {
        // 正则表达式
        let reg = new RegExp(key);
        if (reg.test(item.field)) {
          _define = cloneDeep(defineColumnStyle[key]);

          break;
        }
      }
    }
  }

  _define && _define.hasOwnProperty("fMode") && (_defaultFilter[0].data.fMode = _define.fMode);

  return _defaultFilter;
};

/**
 * @description 搜索方案
 */
export interface searchProjectItem {
  /**
   * @description 名称
   */
  name: string;
  value: { [key: string]: any };
}

/**
 * @description 保存布局，额外的属性
 */
export interface dwnameSaveLayoutAttr {
  /**
   * @description vxetable属性
   */
  scrollY?: any;
  /**
   * @description 搜索栏相关属性
   */
  search?: any;
  /**
   * @description 详情页相关参数
   */
  basicinfo?: any;
  /**
   * @description 搜索方案
   */
  searchProject?: searchProjectItem[];
}
