package cn.com.smart.form.service;

import cn.com.smart.bean.SmartResponse;
import cn.com.smart.exception.ServiceException;
import cn.com.smart.form.bean.QueryFormData;
import cn.com.smart.form.bean.entity.TFormFieldMapping;
import cn.com.smart.form.bean.entity.TFormMapping;
import cn.com.smart.report.bean.entity.*;
import cn.com.smart.service.impl.MgrServiceImpl;
import cn.com.smart.web.ISmartWeb;
import cn.com.smart.web.service.IOPService;
import com.mixsmart.exception.NullArgumentException;
import com.mixsmart.utils.CollectionUtils;
import com.mixsmart.utils.LoggerUtils;
import com.mixsmart.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 乌草坡 2019-09-15
 * @since 1.0
 */
@Service
public class FormMappingService extends MgrServiceImpl<TFormMapping> {

    @Autowired
    private FormFieldMappingService fieldMappingServ;
    @Autowired
    private IOPService opServ;
    @Autowired
    private IFormDataService formDataServ;

    @Override
    public SmartResponse<String> delete(String id) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<String>("删除失败");
        if(StringUtils.isEmpty(id)) {
            return smartResp;
        }
        Map<String, Object> param = new HashMap<String, Object>(1);
        param.put("ids", id);
        smartResp = opServ.execute("delete_form_mapping", param);
        if(OP_SUCCESS.equals(smartResp.getResult())) {
            smartResp.setMsg("删除成功");
        }
        return smartResp;
    }

    /**
     * 保存或更新表单映射信息
     * @param formMapping 表单映射实体类
     * @return 返回结果
     */
    public SmartResponse<String> saveOrUpdate(TFormMapping formMapping) {
        SmartResponse<String> smartResp = new SmartResponse<String>();
        checkRequire(formMapping);
        if(StringUtils.isEmpty(formMapping.getId())) {
            smartResp = this.save(formMapping);
        } else {
            smartResp = this.update(formMapping);
        }
        return smartResp;
    }

    @Override
    public SmartResponse<String> save(TFormMapping formMapping) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<>();
        if(CollectionUtils.isEmpty(formMapping.getFieldMappings())) {
            smartResp.setMsg("映射字段不能为空");
            return smartResp;
        }
        //判断映射关系是否已经存在
        Map<String, Object> param = new HashMap<>(2);
        param.put("formId", formMapping.getFormId());
        param.put("targetFormId", formMapping.getTargetFormId());
        SmartResponse<Long> countResp = opServ.count("check_form_mapping_exist", param);
        if(countResp.getData() > 0) {
            smartResp.setResult(OP_FAIL);
            smartResp.setMsg("两个表单的映射关系已经配置，请不要重复配置！");
            return smartResp;
        }
        smartResp = super.save(formMapping);
        if(OP_SUCCESS.equals(smartResp.getResult())) {
            saveFieldMapping(formMapping);
        }
        return smartResp;
    }

    /**
     * 保存字段映射信息
     * @param formMapping
     */
    private void saveFieldMapping(TFormMapping formMapping) {
        for (TFormFieldMapping fieldMapping : formMapping.getFieldMappings()) {
            fieldMapping.setFormMappingId(formMapping.getId());
            //标题为空的字段不保存
            if(StringUtils.isNotEmpty(fieldMapping.getFieldId()) &&
                    StringUtils.isNotEmpty(fieldMapping.getTargetFieldId())) {
                fieldMappingServ.save(fieldMapping);
            }
        }
    }

    @Override
    public SmartResponse<String> update(TFormMapping formMapping) throws ServiceException {
        SmartResponse<String> smartResp = new SmartResponse<>();
        if(CollectionUtils.isEmpty(formMapping.getFieldMappings())) {
            smartResp.setMsg("映射字段不能为空");
            return smartResp;
        }
        smartResp = super.update(formMapping);
        if(OP_SUCCESS.equals(smartResp.getResult())) {
            fieldMappingServ.deleteByFormMappingId(formMapping.getId());
            saveFieldMapping(formMapping);
        }
        smartResp.setResult(OP_SUCCESS);
        smartResp.setMsg("修改成功");
        return smartResp;
    }

    /**
     * 关联查询表单映射对象
     * @param id 表单映射ID
     * @return 返回表单映射体类（包含映射字段实体数据）
     */
    public TFormMapping queryAssoc(String id) {
        if(StringUtils.isEmpty(id)) {
            throw new NullArgumentException();
        }
        TFormMapping formMapping = super.find(id).getData();
        Map<String, Object> param = new HashMap<String, Object>(1);
        param.put("formMappingId", id);

        List<TFormFieldMapping> fieldMappings = fieldMappingServ.findByParam(param, " sortOrder asc ").getDatas();
        if(CollectionUtils.isNotEmpty(fieldMappings)) {
            formMapping.setFieldMappings(fieldMappings);
        }
        return formMapping;
    }

    /**
     * 关联查询表单映射对象
     * @param sourceFormId 表单映射ID
     * @param targetFormId
     * @return 返回表单映射体类（包含映射字段实体数据）
     */
    public TFormMapping queryAssoc(String sourceFormId, String targetFormId) {
        if(StringUtils.isEmpty(sourceFormId) || StringUtils.isEmpty(targetFormId)) {
            return null;
        }
        Map<String, Object> param = new HashMap<>(2);
        param.put("formId", sourceFormId);
        param.put("targetFormId", targetFormId);
        TFormMapping formMapping = null;
        SmartResponse<TFormMapping> queryResp = super.findByParam(param);
        if(OP_SUCCESS.equals(queryResp.getResult())) {
            formMapping = queryResp.getDatas().get(0);
            param.clear();
            param = new HashMap<String, Object>(1);
            param.put("formMappingId", formMapping.getId());
            List<TFormFieldMapping> fieldMappings = fieldMappingServ.findByParam(param, " sortOrder asc ").getDatas();
            if(CollectionUtils.isNotEmpty(fieldMappings)) {
                formMapping.setFieldMappings(fieldMappings);
            }
        }
        return formMapping;
    }

    /**
     * 验证必填属性
     * @param formMapping 表单映射实体类
     */
    private void checkRequire(TFormMapping formMapping) {
        if(StringUtils.isEmpty(formMapping.getFormId())
                || StringUtils.isEmpty(formMapping.getTargetFormId())
                || null == formMapping.getFieldMappings()) {
            throw new NullArgumentException("必填字段为空");
        }
    }


    /**
     * 获取映射后的数据
     * @param sourceFormId 来源表单Id
     * @param sourceFormDataId 来源表单数据Id
     * @param targetFormId 目标表单ID
     * @return 返回查询结果
     */
    public SmartResponse<QueryFormData> getFormDataMapping(String sourceFormId, String sourceFormDataId, String targetFormId) {
        SmartResponse<QueryFormData> sourceFormDataResp = formDataServ.getFormDataByFormDataId(sourceFormDataId, sourceFormId);
        if(!ISmartWeb.OP_SUCCESS.equals(sourceFormDataResp.getResult())) {
            return null;
        }
        SmartResponse<QueryFormData> targetFormDataResp = formDataServ.getFormDataByFormDataId(null, targetFormId);
        if(!OP_SUCCESS.equals(targetFormDataResp.getResult())) {
            return null;
        }
        TFormMapping formMapping = queryAssoc(sourceFormId, targetFormId);
        if(null == formMapping || CollectionUtils.isEmpty(formMapping.getFieldMappings())) {
            return null;
        }
        List<QueryFormData> targetFormDatas = targetFormDataResp.getDatas();
        boolean isAssignment = false;
        for(QueryFormData targetFormData : targetFormDatas) {
            QueryFormData formData = getFieldMappingValue(targetFormData.getFieldId(), formMapping.getFieldMappings(), sourceFormDataResp.getDatas());
            if(null != formData) {
                targetFormData.setValue(formData.getValue());
                targetFormData.setValueSize(formData.getValueSize());
                isAssignment = true;
            } else if(CollectionUtils.isNotEmpty(targetFormData.getNameMoreValues())) {
                for(QueryFormData listFormData : targetFormData.getNameMoreValues()) {
                    formData = getFieldMappingValue(listFormData.getFieldId(), formMapping.getFieldMappings(), sourceFormDataResp.getDatas());
                    if(null != formData) {
                        listFormData.setValue(formData.getValue());
                        listFormData.setValueSize(formData.getValueSize());
                        isAssignment = true;
                    }
                }
            }
        }
        return isAssignment?targetFormDataResp:null;
    }

    /**
     * 获取字段映射值
     * @param targetFieldId
     * @param fieldMappings
     * @param sourceFormDatas
     * @return
     */
    private QueryFormData getFieldMappingValue(String targetFieldId, List<TFormFieldMapping> fieldMappings, List<QueryFormData> sourceFormDatas) {
        String sourceFieldId = getSourceFieldIdByMapping(targetFieldId, fieldMappings);
        if(StringUtils.isEmpty(sourceFieldId)) {
            return null;
        }
        QueryFormData formData = getSourceFormDataValue(sourceFieldId, sourceFormDatas);
        return formData;
    }

    /**
     * 递归获取原表单数据值
     * @param sourceFieldId
     * @param sourceFormDatas
     * @return
     */
    private QueryFormData getSourceFormDataValue(String sourceFieldId, List<QueryFormData> sourceFormDatas) {
        QueryFormData formData = null;
        for(QueryFormData sourceFormData: sourceFormDatas) {
            if(sourceFormData.getFieldId().equals(sourceFieldId)) {
                formData = sourceFormData;
                break;
            } else if(CollectionUtils.isNotEmpty(sourceFormData.getNameMoreValues())) {
                formData = getSourceFormDataValue(sourceFieldId, sourceFormData.getNameMoreValues());
                if(null != formData) {
                    break;
                }
            }
        }
        return formData;
    }

    /**
     * 获取原表单字段ID根据映射数据
     * @param targetFieldId
     * @param fieldMappings
     * @return
     */
    private String getSourceFieldIdByMapping(String targetFieldId, List<TFormFieldMapping> fieldMappings) {
        String sourceFieldId = null;
        for(TFormFieldMapping fieldMapping : fieldMappings) {
            if(fieldMapping.getTargetFieldId().equals(targetFieldId)) {
                sourceFieldId = fieldMapping.getFieldId();
                break;
            }
        }
        return sourceFieldId;
    }
}
