package com.yeejoin.equipmanage.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.equipmanage.common.entity.FormGroupColumnEquip;
import com.yeejoin.equipmanage.common.entity.FormGroupEquip;
import com.yeejoin.equipmanage.common.entity.FormInstanceEquip;
import com.yeejoin.equipmanage.common.entity.dto.FormGroupColumnEquipDto;
import com.yeejoin.equipmanage.common.enums.GroupCodeEnum;
import com.yeejoin.equipmanage.common.enums.GroupColumnDataType;
import com.yeejoin.equipmanage.common.utils.CommonResponseUtil;
import com.yeejoin.equipmanage.common.utils.RandomUtil;
import com.yeejoin.equipmanage.mapper.FormInstanceEquipMapper;
import com.yeejoin.equipmanage.service.IFormGroupColumnEquipService;
import com.yeejoin.equipmanage.service.IFormGroupEquipService;
import com.yeejoin.equipmanage.service.IFormInstanceEquipService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.StringUtil;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DELL
 */
@Service
public class FormInstanceEquipServiceImpl extends ServiceImpl<FormInstanceEquipMapper, FormInstanceEquip> implements IFormInstanceEquipService {

    @Autowired
    private IFormGroupColumnEquipService formGroupColumnEquipService;

    @Autowired
    private IFormInstanceEquipService formInstanceEquipService;

    @Autowired
    private IFormGroupEquipService formGroupEquipService;

    @Autowired
    private FormInstanceEquipMapper formInstanceEquipMapper;

    @Autowired
    private Sequence sequence;

    final static String[] list = {"92031900", "92011000", "92010700"};

    private final String CODE = "code";

    private final String ORGCODE = "orgCode";


    @Override
    public List<FormGroupColumnEquipDto> queryColumnAndValueByGroup(String groupCode, Long instanceId) {
        List<FormGroupColumnEquipDto> list = new ArrayList<>();
        List<FormGroupColumnEquip> columnList = formGroupColumnEquipService.queryByGroup(groupCode);
        if (!CollectionUtils.isEmpty(columnList)) {
            Map<String, Object> map = queryForMap(instanceId);
            columnList.forEach(x -> {
                FormGroupColumnEquipDto dto = new FormGroupColumnEquipDto();
                BeanUtils.copyProperties(x, dto);
                if (!map.isEmpty()) {
                    dto.setFieldValue(map.get(dto.getFieldName()).toString());
                }
                list.add(dto);
            });
        }
        return list;
    }

    private String fillCode(String groupCode, String fieldName, String value, String companyCode) {
        if (CODE.equals(fieldName) && StringUtils.isEmpty(value)) {
            return RandomUtil.buildNo(GroupCodeEnum.getInstance(groupCode).getSequenceType(), companyCode);
        } else if (ORGCODE.equals(fieldName) && StringUtils.isEmpty(value)) {
            return companyCode;
        }
        return value == null ? "" : value;
    }

    private String checkAndFillCode(String companyCode, Map<String, Object> map, String groupCode, FormGroupColumnEquip optionModel) {
        Object value = map.get(optionModel.getFieldName());
        String stringValue = this.fillCode(groupCode, optionModel.getFieldName(), value == null ? null : String.valueOf(value), companyCode);
        // 检验code重复
        if ("code".equals(optionModel.getFieldName())) {
            String instanceId = String.valueOf(map.get("instanceId"));
            int count = this.count(new QueryWrapper<FormInstanceEquip>().eq("field_value", stringValue).eq("field_name", "code").ne("instance_id", instanceId == null ? "" : instanceId));
            if (count > 0) {
                if (value == null) {
                    stringValue = checkAndFillCode(companyCode, map, groupCode, optionModel);
                } else {
                    throw new BadRequest("编码重复！");
                }
            }
        }
        if (StringUtils.isEmpty(stringValue) && optionModel.getNotNull()) {
            throw new BadRequest(optionModel.getFieldLabel() + " 不能为空");
        }
        return stringValue;
    }

    private Map<String, Object> queryForMap(Long instanceId) {
        Map<String, Object> optionListMap = new HashMap<>();
        List<FormInstanceEquip> list = this.queryByInstanceId(instanceId);
        if (!CollectionUtils.isEmpty(list)) {
            List<FormGroupColumnEquip> optionList = formGroupColumnEquipService.queryByGroup(list.iterator().next().getGroupCode());
            optionListMap = Bean.listToMap(optionList, "fieldName", "fieldLabel", FormGroupColumnEquip.class);
            Map instanceMap = Bean.listToMap(list, "fieldName", "fieldValue", FormInstanceEquip.class);
            for (FormGroupColumnEquip optionModel : optionList) {
                instanceMap.put(optionModel.getFieldName(), this.dataTypeProcess(optionModel.getFieldName(), instanceMap.get(optionModel.getFieldName()), optionModel.getDataType(), instanceMap));
            }
            optionListMap.putAll(instanceMap);
            optionListMap.put("instanceId", instanceId);
            optionListMap.put("createTime", list.iterator().next().getCreateDate());
            optionListMap.put("groupCode", list.iterator().next().getGroupCode());
        }
        return optionListMap;
    }

    private Object dataTypeProcess(String fieldName, Object value, String dataType, Map instanceMap) {
        Object retValue = value;
        if (!ValidationUtil.isEmpty(value)) {
            GroupColumnDataType optionDataType = GroupColumnDataType.valueOf(dataType);
            switch (optionDataType) {
                case InstanceId:
                    List<Long> instanceIds = StringUtil.String2LongList(String.valueOf(value));
                    List<Map<String, Object>> mapList = new ArrayList<>();
                    instanceIds.forEach((id) -> mapList.add(queryForMap(id)));
                    retValue = mapList;
                    break;
                case Enum:
                    Map<String, Map<String, Object>> map = formGroupColumnEquipService.processEnumData(fieldName, String.valueOf(value));
                    instanceMap.putAll(map);
                    break;
                default:
                    break;
            }
        }
        return retValue;
    }

    public List<FormInstanceEquip> queryByInstanceId(Long instanceId) {
        QueryWrapper<FormInstanceEquip> wrapper = new QueryWrapper<>();
        wrapper.eq("instance_id", instanceId);
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = {BaseException.class, Exception.class})
    public Map<String, Object> createByMap(String groupCode, String companyCode, Map<String, Object> map, String caseId) {
        //1.查询分组表数据，数据准备用
        Map<String, Object> returnMap = new HashMap<>();
        FormGroupEquip formGroup = formGroupEquipService.getByUniqueKey(groupCode);
        //2.查询分组对应的动态表单字段
        List<FormGroupColumnEquip> optionList = formGroupColumnEquipService.queryByGroup(groupCode);
        if (CollectionUtils.isEmpty(map) || formGroup == null) {
            return returnMap;
        }
        Long instanceId = sequence.nextId();
        if (!ValidationUtil.isEmpty(Arrays.stream(list).filter(x -> x.equals(groupCode)).collect(Collectors.toList()))) {
            instanceId = Long.valueOf(caseId);
            returnMap.put("code", sequence.nextId());
        }
        List<FormInstanceEquip> entities = new ArrayList<>();
        //3.以数据库现在配置的动态表单字段为准，进行数据插入的准备
        for (FormGroupColumnEquip option : optionList) {
            String stringValue = checkAndFillCode(companyCode, map, groupCode, option);
            FormInstanceEquip formInstance = new FormInstanceEquip();
            Bean.copyExistPropertis(option, formInstance);
            buildEntry(instanceId, formGroup, entities, option, stringValue, formInstance);
        }
        //4.批量插入
        this.saveBatch(entities);
        //5.返回值对象(数据暂时未用到)
        returnMap = Bean.listToMap(entities, "fieldName", "fieldValue", FormInstanceEquip.class);
        returnMap.put("instanceId", entities.iterator().next().getInstanceId());
        return returnMap;
    }

    private void buildEntry(Long instanceId, FormGroupEquip formGroup, List<FormInstanceEquip> entities, FormGroupColumnEquip optionModel, String stringValue, FormInstanceEquip formInstance) {
        formInstance.setFieldName(optionModel.getFieldName());
        formInstance.setFieldLabel(optionModel.getFieldLabel());
        formInstance.setDataType(optionModel.getDataType());
        formInstance.setGroupId(optionModel.getGroupId());
        formInstance.setGroupCode(optionModel.getGroupCode());
        formInstance.setQueryStrategy(optionModel.getQueryStrategy());

        formInstance.setFieldValue(stringValue);
        formInstance.setInstanceId(instanceId);
        formInstance.setGroupColumnId(optionModel.getId());
        formInstance.setId(sequence.nextId());
        formInstance.setGroupType(formGroup.getGroupType());
        formInstance.setCreateDate(new Date());
        entities.add(formInstance);
    }

    @Override
    public Object saveForm(String groupCode, String orgCode, Map<String, Object> map, String instanceId) {
        Map<String, Object> formKeyMap = formInstanceEquipService.createByMap(groupCode, orgCode, map, instanceId);
        if (com.yeejoin.equipmanage.common.utils.StringUtil.isNotEmpty(instanceId)) {
            return CommonResponseUtil.success(formKeyMap);
        }
        return formKeyMap;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public Object updateForm(Long instanceId, String orgCode, Map<String, Object> map, String groupCode) {
        if (com.yeejoin.equipmanage.common.utils.StringUtil.isNotEmpty(groupCode)) {
            map.keySet().forEach(x -> {
                formInstanceEquipMapper.updateFormFieldValue(instanceId, x, String.valueOf(map.get(x)));
            });
            return CommonResponseUtil.success();
        }
        return null;
    }

    @Override
    public Boolean deleteInstanceById(Long instanceId) {
        return this.baseMapper.delete(new QueryWrapper<FormInstanceEquip>().lambda().eq(FormInstanceEquip::getInstanceId, instanceId)) > 0;
    }
}
