package com.huigou.uasp.data.application.impl;


import com.alibaba.fastjson.JSON;
import com.google.common.base.CaseFormat;
import com.huigou.data.repository.GeneralRepository;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.operator.OperatorUIElementPermissionBuilder;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.uasp.bpm.engine.domain.model.HistoricTaskInstanceExtension;
import com.huigou.uasp.bpm.engine.repository.HistoricTaskInstanceExtensionRepository;
import com.huigou.uasp.bpm.managment.domain.model.ProcDefinition;
import com.huigou.uasp.bpm.managment.repository.ProcDefinitionRespository;
import com.huigou.uasp.builder.vo.PubDataRecord;
import com.huigou.uasp.builder.vo.SeleListCustomVO;
import com.huigou.uasp.data.application.DataRecordApplication;
import com.huigou.uasp.data.application.DataRecordByFlowApplication;
import com.huigou.uasp.data.domain.query.DataRecordQueryRequest;
import com.huigou.uasp.form.application.CommonUtilApplication;
import com.huigou.uasp.form.domain.model.FormAttribute;
import com.huigou.uasp.form.domain.model.FormSearchSql;
import com.huigou.uasp.form.domain.model.SafFormslist;
import com.huigou.uasp.form.domain.query.SafFormsQueryRequest;
import com.huigou.uasp.form.repository.FormAttributeRepository;
import com.huigou.uasp.form.repository.SafFormslistRepository;
import com.huigou.uasp.model.domain.query.DbTablesQueryRequest;
import com.huigou.uasp.util.Utils;
import com.huigou.util.ApplicationContextWrapper;
import com.huigou.util.SDO;
import org.springframework.util.Assert;

import com.huigou.util.JSONUtil;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang.StringUtils;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Stream;

/**
 * @author lxh
 */
@Service("dataRecordByFlowApplication")
public class DataRecordByFlowApplicationImpl extends FlowBroker implements DataRecordByFlowApplication {

    // private LeaveRepository leaveRepository;
    //private LeaveMapper leaveMapper;

    @Autowired
    private CommonUtilApplication commonUtilApplication;
    @Autowired
    private DataRecordApplication dataRecordApplication;

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ProcDefinitionRespository procDefinitionRespository;
    @Autowired
    private SafFormslistRepository safFormslistRepository;
    @Autowired
    private FormAttributeRepository formAttributeRepository;
    @Autowired
    private GeneralRepository generalRepository;
    @Autowired
    private HistoricTaskInstanceExtensionRepository historicTaskInstanceExtensionRepository;
    @Autowired
    private OperatorUIElementPermissionBuilder operatorUIElementPermissionBuilder;

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        PubDataRecord dataRecord = getBizEntity(PubDataRecord.class);

        if (dataRecord.isNew()) {
            dataRecord.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            dataRecord = (PubDataRecord) commonDomainService.loadAndFillinProperties(dataRecord);
        }
        String apply = getApprovalParameter().getProcUnitId();
        //审批过程的状态:  0  申请  1 审批中  2 挂起  3 已完成  4已归档   5 已终止
        //System.out.println("=ppppppppppp==="+apply+"==="+dataRecord.getStatusId());
        SafFormslist form = safFormslistRepository.findOne(dataRecord.getFormId());

        String tableNames = commonUtilApplication.getTablesByFormId(dataRecord.getFormId(), 1);
        String tableName = tableNames.split(",")[0];  //取第一个是主表


        List<Map<String, Object>> fieldList = this.commonUtilApplication.queryDataRecordSingleFields(form.getId(), tableName.toUpperCase());
        Map<String, Object> map = Utils.dataValueTransfer(fieldList, dataRecord);

        // SimpleDateFormat  sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
        //添加流程所需的默认字段值
        addAuditNeedFields(map, dataRecord);

        SDO sdo = this.getBizAndApprovalData();

        //查找表单存在的隐藏字段
        List<String> hiddenFields = new ArrayList<String>();
        DbTablesQueryRequest dbqueryRequest = new DbTablesQueryRequest();
        dbqueryRequest.setTableName(tableName.toUpperCase());
        hiddenFields = commonUtilApplication.queryTableHiddenFields(dbqueryRequest, 0);
        //获取隐藏字段的值
        String vals = "", tempHiddenStr = "";   //此处的临时隐藏变量 如何获取？？ 需要测试验证
        for (String hiddenStr : hiddenFields) {
            tempHiddenStr = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, hiddenStr); //转成驼峰法
            if (StringUtils.isNotBlank(sdo.getString(tempHiddenStr))) {
                vals = sdo.getString(tempHiddenStr);
                //hiddenStr=CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,hiddenStr);//转成下划线  存入数据库
                map.put(hiddenStr, vals);
            }
        }

        //问题 是当隐藏字段不存在时 如何效验？？ 否则保存出错 ？？？？
        if (dataRecord.getId() != null)
            map.put("id", dataRecord.getId());

        //审批过程中获取修改的字段值  保存到意见中
        //String taskId=sdo.getString("taskId");
        //if ((isApplyProcUnit(apply)) && (getApprovalParameter().isAdvanceProcessAction())) {
        if (isApprovalProcUnit(apply)) {  //当前状态是审批过程中

            String opinions = getModifyFieldsByAudit(getApprovalParameter().getTaskId(), dataRecord.getId(), tableName, map);

            if (!"".equals(opinions)) {
                HistoricTaskInstanceExtension historicTaskInstExtension = this.actApplication.loadHistoricTaskInstanceExtension(getApprovalParameter().getTaskId());
                opinions = historicTaskInstExtension.getOpinion() + "[ " + opinions + "]";
                historicTaskInstExtension.setOpinion(opinions);
                historicTaskInstanceExtensionRepository.save(historicTaskInstExtension);
            }
        }

        DataRecordQueryRequest queryRequest = new DataRecordQueryRequest();
        queryRequest.setMaiTab(tableName);
        queryRequest.setFormId(form.getId());
        queryRequest.setFormNo(form.getFormNo());
        queryRequest.setSaveMode(form.getSaveMode());
        queryRequest.setHiddenField(hiddenFields);

        //保存主表
        String mid = this.dataRecordApplication.saveDataRecord(queryRequest, map);

        System.out.println("主表保存结束：===========" + mid);

        // 先获取到 当前配置的明细表 ，再遍历获取数据值，保存到对应明细表
        String detailTableNames = commonUtilApplication.getTablesByFormId(dataRecord.getFormId(), 2);
        detailTableNames = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, detailTableNames);
        String[] detailTableName = detailTableNames.split(",");
        for (String subTable : detailTableName) {
            List<PubDataRecord> detailDataList = sdo.getList(subTable + "data", PubDataRecord.class);//获取明细数据
            if (detailDataList != null && detailDataList.size() > 0) {
                Map<String, Object> data = this.dataRecordApplication.saveRowDataRecordDetail(form.getId(), mid,
                        subTable, detailDataList);
            }
        }

        return mid;
    }

    @Override
    public ProcDefinition getFormNoByBizid(String bizId) {
        //String formNo="";
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                .processInstanceBusinessKey(bizId)
                .singleResult();

        //System.out.println("getDeploymentId:"+pi.getDeploymentId());
        RepositoryService repositoryService = ApplicationContextWrapper.getBean(RepositoryService.class);

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(pi.getProcessDefinitionId())
                .singleResult();

        //System.out.println("processDefinition.getKey====="+processDefinition.getKey());
        String procId = processDefinition.getKey();

        ProcDefinition pd = procDefinitionRespository.findOne(((root, query, cb) ->
                cb.and(cb.equal(root.get("procId"), procId), cb.equal(root.get("nodeKindId"), "proc")))
        );
        return pd;
    }


    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例，
        ProcDefinition pd = getFormNoByBizid(bizId);

        System.out.println("formNo==pd=======" + pd.getFormNo());
        List<SafFormslist> list = safFormslistRepository.findByFormNo(pd.getFormNo());
        SafFormslist safFormslist = list.get(0);

        String tableName = commonUtilApplication.getTablesByFormId(safFormslist.getId(), 1);
        tableName = tableName.split(",")[0];  //取第一个主表

        List<Map<String, Object>> fieldList = this.commonUtilApplication.queryDataRecordSingleFields(safFormslist.getId(), tableName.toUpperCase());
        String columns = Utils.getDataFields(fieldList, "fieldCode");

        String sql = "select " + columns + " from " + tableName + " where id='" + bizId + "'";
        // List <?>listVal=generalRepository.queryByNativeSql(sql,new HashMap<>());
        List<Map<String, Object>> listVal = this.commonUtilApplication.queryFormTableDatas(sql);
        System.out.println("========listVal=======" + listVal);
        return listVal.get(0);
        // return ClassHelper.toMap(leaveRepository.getOne(bizId));

    }

    @Override
    public void onComplete(DelegateTask delegateTask) {
        super.onComplete(delegateTask);
        System.out.println("getFormKey==pd=======" + delegateTask.getFormKey());
        DelegateExecution delegateExecution = delegateTask.getExecution();
        String bizId = delegateExecution.getProcessBusinessKey();
        System.out.println("bizId pd=======" + bizId);
        //更新状态值
        if ((isApplyProcUnit(delegateTask)) && (getApprovalParameter().isAdvanceProcessAction())) {
            System.out.println("getApprovalParameter pd=======" + bizId);
            updateStatus(bizId, BizBillStatus.APPROVING.getId());
        }

    }

    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        System.out.println("onBeforeComplete  bizId=======" + bizId);
        if ((isApplyProcUnit(delegateTask)) && (getApprovalParameter().isAdvanceProcessAction())) {
            updateStatus(bizId, BizBillStatus.APPROVING.getId());
        }
    }

    @Transactional
    private void updateStatus(String bizId, Integer status) {
        Assert.hasText(bizId, "参数id不能为空。");
        // this.commonDomainService.updateStatus(PubDataRecord.class, bizId, status);
        ProcDefinition pd = getFormNoByBizid(bizId);
        SafFormslist safFormslist = safFormslistRepository.findByFormNo(pd.getFormNo()).get(0);

        String tableName = commonUtilApplication.getTablesByFormId(safFormslist.getId(), 1);
        tableName = tableName.split(",")[0];  //取第一个主表
        String updateSql = "update " + tableName + " set status=" + status + " where id='" + bizId + "'";
        System.out.println("updateStatus  bizId=======" + updateSql);
        this.generalRepository.updateByNativeSql(updateSql, new HashMap<String, Object>());
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
      /*  Leave leave = leaveRepository.findOne(bizId);
        leave.setStatusId(status.getId());
        leaveRepository.save(leave);*/
        System.out.println("onEnd=======" + bizId);

    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
       /* Leave leave = leaveRepository.findOne(bizId);
        leave.setStatusId(BizBillStatus.ABORTED.getId());
        leaveRepository.save(leave);*/
        System.out.println("onAbortProcessInstance=======" + bizId);
    }

    /**
     * @param delegateTask
     * @param destActivityId 回退到的目标节点id
     */
    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
      /*  if ("Apply".equalsIgnoreCase(destActivityId)) {
            String bizId = delegateTask.getExecution().getProcessBusinessKey();
            Leave leave = leaveRepository.findOne(bizId);
            leave.setStatusId(BizBillStatus.APPLYING.getId());
            leaveRepository.save(leave);
        }*/
    }

    //获取审批过程中 修改字段的旧值和新值
    private String getModifyFieldsByAudit(String taskId, String id, String tableName, Map<String, Object> map) {
        List<Map<String, Object>> uiFields = operatorUIElementPermissionBuilder.queryUIElementPermissionsByTaskId(taskId);
        String modifyColCode = "", modifyColName = "";
        FormAttribute formAttribute = null;
        StringBuffer opinions = new StringBuffer("");

        for (Map mapf : uiFields) {
            if (mapf.get("formFieldId") != null && !"readwrite".equals(mapf.get("formFieldId").toString())) {
                modifyColCode += ",";
                modifyColName += ",";
                formAttribute = formAttributeRepository.findOne(mapf.get("formFieldId").toString());
                modifyColCode += formAttribute.getAttrCode();
                modifyColName += formAttribute.getAttrName();
            }
        }
        if (!"".equals(modifyColCode)) {   //存在审批过程修改的列
            //查询旧值
            String sql = "select " + modifyColCode + " from " + tableName + " where id='" + id + "'";
            List list = this.generalRepository.queryByNativeSql(sql, new HashMap<>());
            // if (list!=null&&list.size()>0) {
            String[] fields = modifyColCode.split(",");
            String[] names = modifyColName.split(",");
            Object[] obj = null;
            if (list != null && list.size() > 0) {
                obj = (Object[]) list.get(0);
            }
            for (int u = 0; u < fields.length; u++) {
                opinions.append(names[u]).append(" 旧值:").append(obj != null && obj[u] != null ? obj[u].toString() : "")
                        .append("新值").append(map.get(fields[u]).toString());
            }
        }
        return opinions.toString();
    }

    //添加流程审批需求字段的默认值
    private Map<String, Object> addAuditNeedFields(Map<String, Object> map, PubDataRecord dataRecord) {
        map.put("bill_code", dataRecord.getBillCode());
        // map.put("fillin_date",sysdate);
        map.put("organ_id", dataRecord.getOrganId());
        map.put("organ_name", dataRecord.getOrganName());
        map.put("dept_id", dataRecord.getDeptId());
        map.put("dept_name", dataRecord.getDeptName());
        map.put("position_id", dataRecord.getPositionId());
        map.put("position_name", dataRecord.getPositionName());
        map.put("person_member_id", dataRecord.getPersonMemberId());
        map.put("person_member_name", dataRecord.getPersonMemberName());
        map.put("full_id", dataRecord.getFullId());
        map.put("status", dataRecord.getStatusId());
        return map;
    }
}
