import {onMounted, watch} from 'vue';
import {RouteLocationNormalizedLoaded, useRoute} from 'vue-router';
import Schema, {ErrorList, FieldErrorList} from 'async-validator';
import api from '/@/api';
import commonUtil from '/@/utils/commonUtil';
import {confirm, notify} from '/@/utils/message';
import {IPageParams} from './page.types';
import {tabRouter} from '/@/pages/layout/tab/useTab';

interface IDatasetEvent {
  action: string
  dataset: any
  row: any
}

export class PageDataset {
  private params: IPageParams;
  readonly data: any;
  readonly page: any;
  private eventHandle?: Function;

  constructor(route: RouteLocationNormalizedLoaded, data: any, page: any) {
    // title: this.$route.query.title,
    // 页面参数

    this.params = {
      pageId: route.params.pageI || page.id,
      id: route.params.id as string,
      parentId: route.params.parentId as string,
    };

    this.data = data;
    this.page = page;
    // 混入的主页面需要提供 page 和 data
  }

  setEventHandle(eventHandle: Function) {
    this.eventHandle = eventHandle;
  }

  // 通过dataset对象读取数据
  async loadDataset(dataset: any, row?: any, params?: any, callFn?: Function) {
    if (row && dataset.masterFields) {
      // 处理子表过滤条件
      const filter = [];

      for (const mapField of dataset.masterFields) {
        filter.push({ field: mapField.slave, keyword: row[mapField.master] });
      }

      dataset.filter = filter;
    }

    switch (dataset.listModel) {
      case 1:
        await this.loadList(dataset.name, params, callFn);
        break;
      case 2:
        await this.loadTree(dataset.name, params, callFn);
        break;
      default:
        await this.loadCard(dataset.name, params, callFn);
        break;
    }
  }

  // async searchList() {
  //   // 点击搜索按钮
  //   if (this.getMainDatasetId()) {
  //     await this.loadList(this.getMainDatasetId(), 0);
  //   }
  // }
  //
  // async resetList() {
  //   // 重置按钮
  //   if (this.getMainDatasetId()) {
  //     const dataset = this.getDatasetById(this.getMainDatasetId());
  //     // this.$set(dataset, 'form', {});
  //     dataset.form = {};
  //     await this.loadList(this.getMainDatasetId(), 0);
  //   }
  // }
  //
  // getMainDatasetId(): string | null {
  //   const { datasets } = this.page;
  //   if (datasets && datasets.length > 0) {
  //     return datasets[0].id;
  //   }
  //   return null;
  // }

  findDatasetMeta(datasetName: string): any {
    return this.page.datasets[datasetName];
    // 得到 datasets
    // return this.page.datasets.find((e: any) => e.id === datasetId || e.name === datasetId);
    // return Object.values(this.page.datasets).find((dataset: any) => {
    //   return dataset.id === datasetId || dataset.name === datasetId;
    // });
  }

  // async loadDatasetById(datasetId: string) {
  //   await this.loadDataset(this.findDataset(datasetId));
  // }

  async loadDatasetByName(name: string, params?: any, callFn?: Function) {
    await this.loadDataset(this.page.datasets[name], null, params, callFn);
  }

  async doApi(name: string, params: any): Promise<any> {
    const dataset = this.findDatasetMeta(params.dataset);
    let url = null;
    if (dataset && dataset.apis) {
      url = dataset.apis[name];
    }

    if (!url) {
      switch (name) {
        case 'cardGet':
          url = 'bpm/DynFormCard/load';
          break;
        case 'cardSave':
          url = 'bpm/DynFormCard/save';
          break;
        case 'cardDel':
          url = 'bpm/DynFormCard/remove';
          break;
        case 'listGet':
          url = 'bpm/DynFormList/list';
          break;
        case 'listCount':
          url = 'bpm/DynFormList/count';
          break;
        case 'treeAll':
          url = 'bpm/DynFormTree/treeAll';
          break;
        case 'treeGet':
          url = 'bpm/DynFormTree/tree';
          break;
        case 'treeMove':
          url = 'bpm/DynFormTree/move';
          break;
      }
    }
    if (url) {
      return await api.post(url, params);
      // return await api.post(url, params);
    }

    return {};
  }

  // async doCustomApi(apiName: string, params: any, callFn: Function) {
  //   // 执行自定义的API
  //   const re = await api.post(apiName, params);
  //   if (callFn) {
  //     callFn(re);
  //   }
  // }

  async loadCard(datasetName: string, params: any, callFn?: Function) {
    const ds = this.loadDatasetData(datasetName);
    console.log('loadCard= ', this.params.id, ds);
    if (this.params.id) {
      // 查询一条数据
      const { data } = await this.doApi('cardGet', {
        pageId: this.page.id,
        dataset: datasetName,
        id: this.params.id,
        filter: ds.filter,
      });

      if (data) {
        ds.form = data;

        this.scrollDataset(datasetName, data);
      }

      if (callFn) {
        callFn(data);
      }
    }
  }

  loadDatasetData(datasetName: string | null): any {
    if (datasetName) {
      return this.data[datasetName];
    }

    return null;
  }

  async loadList(datasetName: string | null, pageIndex: number, callFn?: Function) {
    const ds = this.loadDatasetData(datasetName);

    if (!ds) {
      console.error(`not find dataset name: ${datasetName}`);
      return;
    }

    const params = {
      pageId: this.page.id,
      parentId: this.params.parentId,
      dataset: datasetName,
      pageIndex,
      pageSize: ds.list.pageSize,
      filter: ds.list.filter,
      // search: ds.list.search || [],
      // searchType: ds.list.searchType,
      // params: { ...(ds.form || {}), ..._search },
    };

    ds.list.loading = true;
    const { data } = await this.doApi('listGet', params);
    ds.list.loading = false;

    if (data) {
      ds.list.data = data.rows;

      // console.log(this.data, data.rows.length);

      if (ds.list.total < 0) { // 不需要每次都查询条数和统计
        try {
          // 更新总数
          if (data.total < 0) {
            // 异步加载数据总数和统计数据
            const retCount = await this.doApi('listCount', params);
            if (retCount.data) {
              ds.list.total = retCount.data.total / 1; // (sql条数是java long类型)
              ds.list.summary = retCount.data;
            }
          } else {
            ds.list.total = data.total;
          }
        } catch (e) {
          console.log('e', e);
        }
      }

      this.scrollDataset(datasetName!);
    }

    if (callFn) {
      callFn(data);
    }
  }

  async loadTree(datasetName: string, params = {}, callFn?: Function) {
    // 加载树数据
    const ds = this.loadDatasetData(datasetName);

    ds.list.loading = true;
    const ret = await this.doApi('treeAll', {
      ...params,
      pageId: this.page.id,
      dataset: datasetName,
    });
    ds.list.loading = false;
    if (ret.data) {
      ds.list.data = ret.data || [];
      this.scrollDataset(datasetName, null);
      if (callFn) {
        callFn();
      }
    }
  }

  scrollDataset(datasetName: string, row?: any) {
    // 加载从表数据
    Object.values(this.page.datasets).forEach((dataset: any) => {
      if (dataset && dataset.tableType === 2 && dataset.master === datasetName) {
        if (row) {
          this.loadDataset(dataset, row);
        } else {
          // 直接清空
          this.scrollDataset(dataset.id, null);
          const slaveData = this.loadDatasetData(dataset.name);
          slaveData.list.data.length = 0;
        }
      }
    });

    this.doEvent({ action: 'afterScroll', dataset: datasetName, row });
  }

  _removeItem(listData: any, id: string, _mainField: string) {
    if (!_mainField) {
      _mainField = 'id'; // 对比的键
    }
    for (let i = 0; i < listData.length; i++) {
      const child = listData[i];
      if (child[_mainField] === id) {
        listData.splice(i, 1);
        return true;
      }

      if (child.children) {
        if (this._removeItem(child.children, id, _mainField)) {
          return true;
        }
      }
    }

    return false;
  }

  _doSave(datasetName: string, formData: any, callFn: Function) {
    this.doApi('cardSave', {
      ...formData,
      pageId: this.page.id,
      id: this.params.id,
      parentId: this.params.parentId,
      dataset: datasetName,
    }).then((ret) => {
      this.params.id = ret.data;
      notify.success('操作成功');
      if (callFn) {
        callFn(ret);
      }
    });
  }

  onSubmit(datasetName: string, isReturn = false) {
    if (datasetName) {
      const ds = this.loadDatasetData(datasetName);
      const formData = ds.form;
      formData.parentId = this.params.parentId;
      const dataset = this.findDatasetMeta(datasetName);
      console.log('onSubmit', formData, dataset);

      if (dataset && dataset.rules && !commonUtil.isEmptyObj(dataset.rules)) {
        const validator = new Schema(dataset.rules);
        validator.validate(formData, {}, (errors: ErrorList, fields: FieldErrorList) => {
          if (errors) {
            // validation failed, errors is an array of all errors
            // fields is an object keyed by field name with an array of
            // errors per field
            console.log(errors, fields);
            notify.error('验证失败');
          } else {
            this._doSave(datasetName, formData, () => {
              if (isReturn) {
                this.goBack();
              }
            });
          }
          // validation passed
        });
      } else {
        if (!this.customValidator(datasetName)) {
          return;
        }
        this._doSave(datasetName, formData, () => {
          if (isReturn) {
            this.goBack();
          }
        });
      }
    }
  }

  customValidator(datasetName: string) {
    // 验证成功 返回 true  失败 返回 false
    // 自定义 输入 验证
    const ds = this.loadDatasetData(datasetName);
    if (ds) {
      const formData = ds.form || {};
      let _b = true;
      console.log('customValidator', formData);
      if (this.page && this.page.widgets) {
        const { widgets = {} } = this.page;
        // 验证必填 （只验证是否有值，不能格式）
        Object.values(widgets).forEach((_widget: any) => {
          if (_widget.dataset === datasetName && _widget.required) {
            const _name = _widget.name || _widget.field;
            if (!commonUtil.isEmpty(_name)) {
              if (commonUtil.isEmpty(formData[_name])) {
                _b = false;
                _widget.showError = true;
              } else {
                _widget.showError = false;
              }
            }
          }
        });
      }
      return _b;
    }
    return false;
  }

  goBack() {
    // 返回上一页面
    tabRouter.back();
    // router.back();
  }

  getIdFieldByDataset(datasetName: string) {
    // 得到 dataset 的ID属性值
    if (this.page && this.page.datasets && this.page.datasets[datasetName]) {
      return this.page.datasets[datasetName].idField;
    }
    return null;
  }

  // 生成查询条件用于向后台提交参数
  _buildSearch(datasetId: string, ds: any): Array<any> {
    // 用户输入的搜索条件
    const result: any[] = [];

    const { widgets } = this.page;

    Object.keys(this.page.widgets).forEach((key) => {
      const widget = widgets[key];
      if (widget.dataset === datasetId && widget.field && widget.filterType) {
        const keyword = ds.form[widget.field];
        if (keyword) {
          result.push({ field: widget.field, keyword, op: widget.filterType });
        }
      }
    });

    // const _search = {};
    // if (ds.list.search && ds.list.search.length > 0) {
    //   for (const _obj of ds.list.search) {
    //     if (_obj.field) {
    //       _search[_obj.field] = _obj.keyword;
    //     }
    //   }
    // }

    return result;
  }

  // 界面按钮产生的数据集动作
  async onWidgetAction(datasetName: string, params: any) {
    const ds = this.loadDatasetData(datasetName);
    const dsMeta = this.findDatasetMeta(datasetName);
    // 得到主键值
    if (params.row && dsMeta && dsMeta.idField) {
      params.id = params.row[dsMeta.idField];
      // params.mainField = _mainField;
    }

    console.log('onWidgetAction', params, ds);

    if (params.link) {
      const routeName = this.page.ref.routes[`id_${params.link}`];

      if (routeName) {
        const query = {
          // pageId: params.link,
          action: params.action,
        } as any;

        switch (params.action) {
          case 'button:add':
            query.parentId = this.params.parentId;
            // query.dataParentId = params.parentId;
            break;
          case 'button:edit':
            // query.parentId = params.id || '';
            query.id = params.id;
            // row = JSON.stringify(params.row || {}),
            break;
        }
        await tabRouter.push(routeName, query);
        // await router.push({ name: routeName, params: query });
      // } else {
      //   await router.push({
      //     path: `/form/${params.link}`,
      //     query: { parentId: this.params.id },
      //   });
      } else {
        console.error(`not find link page by id ${params.link}`);
      }
    } else {
      switch (params.action) {
        case 'list:page': // list控件事件
          if (params.reset) {
            ds.list.total = -1;
          }
          ds.list.pageSize = params.pageSize;

          await this.loadList(datasetName, params.pageIndex);
          break;
        case 'list:filter': // list控件事件，快速查询
          ds.list.total = -1;
          ds.list.search = params.search;
          ds.list.searchType = params.searchType;
          ds.list.pageSize = params.pageSize;

          await this.loadList(datasetName, 0);
          break;
        case 'button:search': // 搜索按钮
          ds.list.total = -1;
          ds.list.filter = this._buildSearch(datasetName, ds);
          ds.list.pageSize = params.pageSize;

          await this.loadList(datasetName, 0);
          break;
        case 'button:return':
          this.goBack();
          break;
        case 'button:add':
          // this._load({pageId: params.link, dataParentId: params.parentId, filter: ds.filter});
          // 弹出新页面
          // this.$router.push({ path: '/form/' + params.link, query: { dataParentId: params.parentId, filter: ds.filter }});
          // 替换当前新页面，path需要相同

          // router.push({
          //   path: `/form/${this.page.id}`,
          //   query: {
          //     pageId: params.link,
          //     parentId: this.params.parentId,
          //     dataParentId: params.parentId,
          //     filter: ds.filter,
          //     // title: this.title,
          //   },
          // });
          notify.warning('未配置链接页面');
          break;
        case 'button:edit':
          // this._load({pageId: params.link, id: params.id});
          // 替换当前新页面，path需要相同
          //   router.push({
          //     path: `/form/${this.page.id}`,
          //     query: {
          //       pageId: params.link,
          //       parentId: params.parentId,
          //       id: params.id,
          //       filter: ds.filter,
          //       // title: this.title,
          //       row: JSON.stringify(params.row || {}),
          //     },
          //   });
          break;
        case 'button:save':
          this.onSubmit(datasetName, false);
          break;
        case 'button:saveAndReturn':
          this.onSubmit(datasetName, true);
          break;
        case 'button:submit': {
          const { isReturn } = params;
          this.onSubmit(datasetName, isReturn);
        }
          break;
        case 'button:remove':
          // 删除一条数据
          this.onWidgetActionRemove('此操作将删除当前记录, 是否继续？', datasetName, [params.id], {
            mainField: params.mainField || 'id',
          });
          break;
        case 'button:batchRemove':
          if (params.sels && params.sels.length > 0) {
            const ids = [];

            for (const item of params.sels) {
              ids.push(item.id);
            }

            this.onWidgetActionRemove(`此操作将删除选中的 "${ids.length}" 条记录, 是否继续？`, datasetName, ids);
          }
          break;
        case 'button:move':
          await this.doApi('treeMove', {
            pageId: this.page.id,
            dataset: datasetName,
            id: params.id,
            parentId: params.parentId,
            dataOrders: params.orders,
          });
          break;
        case 'list:selected':
          this.scrollDataset(datasetName, params.row);
          break;
        case 'tree:loadTreeAll':
          await this.loadTree(params.dataset);
          break;
        // case 'event': {
        //   const { events, name, eventName } = params;
        //   params.datasetId = datasetId;
        //   if ((events && events.click) || name) {
        //     let _funName = null;
        //     if (events && events.click) {
        //       _funName = events.click;
        //     } else if (name || eventName) {
        //       _funName = eventName || name;
        //     }
        //     if (_funName && this[_funName]) {
        //       this[_funName](params);
        //       console.info(`call [${_funName}] function success`);
        //     } else {
        //       console.error(`dataset not found [${_funName}] function`);
        //     }
        //   }
        // }
        //   break;
        default:
          console.log('unknown action', params);
          break;
      }
    }
  }

  onWidgetActionRemove(title: string, datasetName: string, ids: Array<any>, otherArgsObj?: any, callFn?: Function) {
    // console.log('onWidgetActionRemove', ids, ids.join());

    confirm('删除确认', () => {
      (async() => {
        const ret = await this.doApi('cardDel', {
          pageId: this.page.id,
          dataset: datasetName,
          ids: ids.join(),
        });
        if (ret && (ret.data || ret.isSuccess)) {
          const listData = this.loadDatasetData(datasetName).list.data;
          let _mainField = null;

          if (otherArgsObj) {
            _mainField = otherArgsObj.mainField;
          } else {
            _mainField = this.getIdFieldByDataset(datasetName);
          }

          for (const id of ids) {
            this._removeItem(listData, id, _mainField);
          }

          callFn && callFn();
          notify.success('删除成功');
        } else {
          notify.error('删除失败');
        }
      })();
    });
  }

  // 处理事件
  doEvent(evtValue: IDatasetEvent) {
    if (this.eventHandle) {
      this.eventHandle(evtValue);
    }
  }

  getWidgetByName(name: string) {
    if (this.page.widgets && name) {
      Object.values(this.page.widgets).find((value: any) => { return value.name === name; });
      // for (const _key in this.page.widgets) {
      //   if (this.page.widgets[_key].name === name) {
      //     return this.page.widgets[_key];
      //   }
      // }
    }
    return null;
  }

  updateData(params: any = {}) {
    // 根据列表组件 更新 row 字段值
    const { dataset, id, fieldName, value } = params;
    const ds = this.loadDatasetData(dataset);
    const idField = this.getIdFieldByDataset(dataset);
    if (ds && idField) {
      const data = ds.list.data;
      for (const _obj of data) {
        if (_obj[idField] === id) {
          _obj[fieldName] = value;
          break;
        }
      }
    }
  }

  async init(loadLookup: boolean) {
    const values = Object.values(this.page.datasets) as any[];

    if (loadLookup) {
      for (const dataset of values) {
        if (dataset.tableType === 3) {
          await this.loadDataset(dataset);
        }
      }
    }

    for (const dataset of values) {
      if (dataset.tableType === 1) {
        await this.loadDataset(dataset);
      }
    }
    // Object.values(this.page.datasets).forEach((dataset: any) => {
    //   if (dataset.tableType === 1 || dataset.tableType === 3) { // master/lookup
    //     this.loadDataset(dataset);
    //   }
    // });
  }

  update(route: RouteLocationNormalizedLoaded) {
    // title: this.$route.query.title,
    // 页面参数
    const id = route.params.id as string;

    if (id !== this.params.id) {
      this.params.id = id;
      this.params.parentId = route.params.parentId as string;
      this.init(false);
    }
  }
}

export const useDataset = (props: any, data: any, page: any) => {
  // console.log('useDataset', route.params);
  const route = useRoute();

  const pageDataset = new PageDataset(route, data, page);

  onMounted(() => {
    pageDataset.init(true);
  });

  watch(() => props.id, () => {
    pageDataset.update(route);
    // console.log('watch', val, route.params);
  });

  // watch('$route.params.id', (val: any) => {
  //   console.log(page.id, val);
  // });

  return pageDataset;
};
