import mergeSchemas from '@utils/schema-merge';
import cloneDeep from 'lodash/cloneDeep';
import pick from 'lodash/pick';
import assign from 'lodash/assign';
import { DateFormat } from '@constants/utils/format-date';

export default function createView(selected: any[]) {
  const result = { attrList: [] as any[], groupList: [] as any[] };
  const MERGED_GROUPS = ['__default', '_advanced', 'dopInfoGroup'];
  const attrMap: Map<string, any> = new Map();
  const groupMap: Map<string, any> = new Map();
  const groupAttr: Map<string, any> = new Map();

  selected.forEach((item) => {
    if (!item.form) {
      return;
    }
    const form = mergeSchemas(item.form);
    const docCode: string = item.code;

    form.attrList?.forEach((attr: { name: any }) => {
      const newAttr = cloneDeep(attr);
      newAttr.name = transformAttrCode(newAttr.name);
      attrMap.set(newAttr.name, transformAttr(newAttr, form, attr.name));
    });

    form.groupList
      ?.filter((group: { attrList: any }) => group.attrList)
      .forEach((group: any) => {
        const newGroup = pick(group, ['label', 'name', 'attrList']);
        if (MERGED_GROUPS.includes(newGroup.name)) {
          if (groupMap.has(newGroup.name)) {
            const group = groupMap.get(newGroup.name);
            newGroup.attrList.forEach((grpAttr: any) => {
              const transformedAttrCode = transformAttrCode(grpAttr);
              if (
                !group.attrList.includes(transformedAttrCode) &&
                attrMap.has(transformedAttrCode)
              ) {
                groupAttr
                  .get(newGroup.name)
                  .push(attrMap.get(transformedAttrCode));
                group.attrList.push(transformedAttrCode);
              }
            });
          } else {
            registerGroup(groupMap, newGroup, groupAttr, attrMap);
          }
        } else {
          newGroup.name = newGroup.name + '_' + docCode;
          registerGroup(groupMap, newGroup, groupAttr, attrMap);
        }
      });
  });

  MERGED_GROUPS.forEach((groupCode) => {
    if (groupAttr.has(groupCode)) {
      groupAttr
        .get(groupCode)
        .forEach((attr: { num: number }, index: number) => {
          attr.num = index * 10;
        });
    }
  });

  groupMap.forEach((value: any) => {
    result.groupList.push(value);
  });

  attrMap.forEach((value: any) => {
    result.attrList.push(value);
  });

  return result;
}

function registerGroup(
  groupMap: Map<string, any>,
  newGroup: any,
  groupAttr: Map<string, any>,
  attrMap: Map<string, any>
) {
  groupMap.set(newGroup.name, newGroup);
  groupAttr.set(newGroup.name, []);
  newGroup.attrList = newGroup.attrList.map((grpAttr: string) => {
    const transformedAttrCode = transformAttrCode(grpAttr);
    if (attrMap.has(transformedAttrCode)) {
      groupAttr.get(newGroup.name).push(attrMap.get(transformedAttrCode));
    }
    return transformedAttrCode;
  });
}

function transformAttr(attr: any, form: any, originalName: any) {
  const template = {
    previewHidden: false,
    editHidden: false,
    editRequired: true,
    editReadOnly: false,
    createHidden: false,
    createReadOnly: false,
    createRequired: true,
  };

  if (attr.type === 'string') {
    attr.view = 'string';
    assign(attr, template);
  } else if (attr.type === 'date') {
    attr.view = 'date';
    attr.props = {
      format: DateFormat.date,
      type: 'date',
    };
    assign(attr, template);
  } else if (attr.type === 'boolean') {
    attr.view = 'boolean';
    attr.props = {
      rightLabel: true,
      type: 'bool',
    };
    assign(attr, template);
  } else if (attr.type === 'linkMN') {
    attr.view = 'cardtable';
    attr.reference.mode = 'table';
    let originalAttrs = attr.reference.listAttrs;
    if (
      form.linkedSchema?.linked?.[originalName] &&
      originalAttrs === undefined
    ) {
      originalAttrs = form.linkedSchema.linked[originalName].attrList;
    }
    attr.reference.listAttrs = [];
    if (originalAttrs) {
      originalAttrs.forEach((linkedAttr: any) => {
        const newTableAttr: any = pick(linkedAttr, ['label', 'name', 'type']);
        newTableAttr.editable = true;
        newTableAttr.hidden = false;
        if (newTableAttr.type === 'date') {
          newTableAttr.props = {
            format: DateFormat.date,
            type: 'date',
          };
        }
        attr.reference.listAttrs.push(newTableAttr);
      });
    }
  } else if (attr.props?.dictionary !== undefined) {
    attr.props = {
      valuesIn: ['label', 'value'],
      optionValue: 'label',
    };
    assign(attr, template);
  }

  if (attr.name === 'document.resDate') {
    attr.view = 'string';
    attr.type = 'string';
  }

  return attr;
}

function transformAttrCode(code: string): string {
  if (code.startsWith('system.')) {
    return code.replace(/^system./, 'applicationSystem.');
  } else if (
    code.startsWith('applicant.') ||
    code.startsWith('delegate.') ||
    code.startsWith('customFields.')
  ) {
    return code;
  } else {
    return 'document.' + code;
  }
}
