package com.zt.plat.module.qms.office.supplier.service;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.security.core.LoginUser;
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
import com.zt.plat.module.bpm.api.task.BpmProcessInstanceApi;
import com.zt.plat.module.bpm.api.task.BpmTaskApi;
import com.zt.plat.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.zt.plat.module.bpm.api.task.dto.BpmTaskApproveReqDTO;
import com.zt.plat.module.bpm.api.task.dto.BpmTaskRespDTO;
import com.zt.plat.module.qms.api.task.BMPCallbackInterface;
import com.zt.plat.module.qms.api.task.dto.QmsBpmDTO;
import com.zt.plat.module.qms.business.config.dal.dataobject.ConfigUserSignatureDO;
import com.zt.plat.module.qms.business.config.service.ConfigUserSignatureService;
import com.zt.plat.module.qms.business.reportdoc.controller.vo.ReportDocumentMainRespVO;
import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentMainDO;
import com.zt.plat.module.qms.common.data.service.DataKeyCheckService;
import com.zt.plat.module.qms.enums.QmsBpmConstant;
import com.zt.plat.module.qms.enums.QmsCommonConstant;
import com.zt.plat.module.qms.enums.QmsSupplierConstant;
import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierEvaluationPageReqVO;
import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierEvaluationRespVO;
import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierEvaluationSaveReqVO;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import com.zt.plat.module.qms.office.supplier.dal.dataobject.SupplierEvaluationDO;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;

import com.zt.plat.module.qms.office.supplier.dal.mapper.SupplierEvaluationMapper;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.*;
import static com.zt.plat.module.qms.enums.QmsBpmConstant.BPM_CALLBACK_BEAN_NAME;

/**
 * 供应商评价 Service 实现类
 *
 * @author 后台管理
 */
@Service("supplierEvaluationService")
@Validated
public class SupplierEvaluationServiceImpl implements SupplierEvaluationService, BMPCallbackInterface {

    @Resource private SupplierEvaluationMapper supplierEvaluationMapper;
    @Resource private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource private BpmTaskApi bpmTaskApi;
    @Resource private ConfigUserSignatureService configUserSignatureService;
    @Resource private DataKeyCheckService dataKeyCheckService;

    @Override
    public SupplierEvaluationRespVO createSupplierEvaluation(SupplierEvaluationSaveReqVO createReqVO) {

        // 插入
        SupplierEvaluationDO supplierEvaluation = BeanUtils.toBean(createReqVO, SupplierEvaluationDO.class);
        supplierEvaluation.setFlowStatus(QmsCommonConstant.NOT_START);
        supplierEvaluationMapper.insert(supplierEvaluation);
        // 返回
        return BeanUtils.toBean(supplierEvaluation, SupplierEvaluationRespVO.class);
    }

    @Override
    public void updateSupplierEvaluation(SupplierEvaluationSaveReqVO updateReqVO) {
        // 校验存在
        validateSupplierEvaluationExists(updateReqVO.getId());
        // 更新
        SupplierEvaluationDO updateObj = BeanUtils.toBean(updateReqVO, SupplierEvaluationDO.class);
        supplierEvaluationMapper.updateById(updateObj);
    }

    @Override
    public void deleteSupplierEvaluation(Long id) {
        // 校验存在
        validateSupplierEvaluationExists(id);
        // 删除
        supplierEvaluationMapper.deleteById(id);
    }

    @Override
        public void deleteSupplierEvaluationListByIds(List<Long> ids) {
        // 校验存在
        validateSupplierEvaluationExists(ids);
        // 删除
        supplierEvaluationMapper.deleteByIds(ids);
        }

    private void validateSupplierEvaluationExists(List<Long> ids) {
        List<SupplierEvaluationDO> list = supplierEvaluationMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(SUPPLIER_EVALUATION_NOT_EXISTS);
        }
    }

    private void validateSupplierEvaluationExists(Long id) {
        if (supplierEvaluationMapper.selectById(id) == null) {
            throw exception(SUPPLIER_EVALUATION_NOT_EXISTS);
        }
    }

    @Override
    public SupplierEvaluationDO getSupplierEvaluation(Long id) {
        return supplierEvaluationMapper.selectById(id);
    }

    @Override
    public PageResult<SupplierEvaluationRespVO> getSupplierEvaluationPage(SupplierEvaluationPageReqVO pageReqVO) {
        return supplierEvaluationMapper.selectPage(pageReqVO);
    }

    @Override
    public CommonResult<SupplierEvaluationRespVO> createProcessInstance(SupplierEvaluationSaveReqVO param) {

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        //当前登录用户昵称
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        Long id = param.getId();
        SupplierEvaluationDO entity = getSupplierEvaluation(id);
        String flowInsId = entity.getFlowInstanceId();

        if(!ObjectUtils.isEmpty(flowInsId)){
            CommonResult<List<BpmTaskRespDTO>> taskRet = bpmTaskApi.getTaskListByProcessInstanceId(flowInsId);
            List<BpmTaskRespDTO> taskList = taskRet.getData();
            if(taskList.isEmpty())
                throw exception0(ERROR_CODE_MODULE_COMMON, "流程任务查询失败，请联系管理员处理");
            String taskId = taskList.get(taskList.size() - 1).getId();
            //驳回后重新提交
            BpmTaskApproveReqDTO reqVO = new BpmTaskApproveReqDTO();
            reqVO.setId(taskId);
            CommonResult<Boolean> result = bpmProcessInstanceApi.approveTask(reqVO);
            if(!result.isSuccess()){
                throw exception0(ERROR_CODE_MODULE_COMMON, result.getMsg());
            }
            entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);
            //todo 生成报告编号  documentCode
            supplierEvaluationMapper.updateById(entity);
            SupplierEvaluationRespVO respVO = BeanUtils.toBean(entity, SupplierEvaluationRespVO.class);
            return CommonResult.success(respVO);
        }
        JSONObject formData = new JSONObject();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        formData.put("mainId",  id);
        formData.put("applyUser",  nickName);
        formData.put("applyUserId",  loginUser.getId());
        formData.put("applyDepartment",  loginUser.getVisitDeptName());
        formData.put("applyDepartmentId",  loginUser.getVisitDeptId());
        formData.put("applyTime",  sdf.format(new Date()));
        Map<String, Object> variables = formData.toJavaObject(Map.class);
        variables.put(BPM_CALLBACK_BEAN_NAME, "supplierEvaluationService"); //流程回调时使用的service
        BpmProcessInstanceCreateReqDTO reqDTO = new BpmProcessInstanceCreateReqDTO();
        reqDTO.setBusinessKey(String.valueOf(id));
        reqDTO.setProcessDefinitionKey(QmsSupplierConstant.EVALUATION_FLOW_KEY);
        reqDTO.setVariables(variables);
        CommonResult<String> result = bpmProcessInstanceApi.createProcessInstance(loginUser.getId(), reqDTO);
        if(!result.isSuccess()){
            throw exception0(ERROR_CODE_MODULE_COMMON, result.getMsg());
        }
        String wfInsId = result.getData();
        entity.setFlowInstanceId(wfInsId);
        entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);
        entity.setEvaluationDate(LocalDateTime.now());
        entity.setEvaluator(nickName);
        supplierEvaluationMapper.updateById(entity);
        SupplierEvaluationRespVO respVO = BeanUtils.toBean(entity, SupplierEvaluationRespVO.class);
        return CommonResult.success(respVO);
    }

    @Override
    public CommonResult<JSONObject> callback(QmsBpmDTO reqDTO) {

        JSONObject variables = reqDTO.getVariables();
        String processInsId = variables.getString(QmsBpmConstant.BPM_PROCESS_INS_ID);
        String currentActivityInsId = variables.getString(QmsBpmConstant.BPM_CUR_ACTIVITY_INS_ID);
        String returnFlag = variables.getString(QmsBpmConstant.BPM_REJECT_TO_FIRST_FLAG); //退回标识。在任务监听中设置
        //同一个节点实例只触发一次
        String checkKey = currentActivityInsId;
        if(ObjectUtils.isEmpty(currentActivityInsId))
            checkKey = processInsId + "-create";
        if("1".equals(returnFlag))
            checkKey += "-reject";
        try{
            dataKeyCheckService.create(checkKey, this.getClass().getName());
        }catch (Exception e){
//            e.printStackTrace();

            return CommonResult.success(new JSONObject());
        }
        //流程状态  1-提交（含退回）  4-取消流程
        String PROCESS_STATUS = variables.getString(QmsBpmConstant.PROCESS_INSTANCE_VARIABLE_STATUS);
        String mainId = variables.getString("mainId");
        JSONArray fieldExtensions = new JSONArray();
        if(variables.containsKey(QmsBpmConstant.BPM_FIELD_EXTENSIONS)){
            fieldExtensions = variables.getJSONArray(QmsBpmConstant.BPM_FIELD_EXTENSIONS);
        }
        SupplierEvaluationDO entity = getSupplierEvaluation(Long.valueOf(mainId));

        String currentActivityId = variables.getString(QmsBpmConstant.BPM_CALLBACK_ACTIVITY_ID);

        //判断是否最后一个节点
        String lastActivityFlag = "0";
        String firstActivityFlag = "0";
        if(!fieldExtensions.isEmpty()){
            for(int i = 0; i < fieldExtensions.size(); i++){
                JSONObject fieldExtension = fieldExtensions.getJSONObject(i);
                if(fieldExtension.getString("fieldName").equalsIgnoreCase(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG)){
                    lastActivityFlag = "1";
                }
                if(fieldExtension.getString("fieldName").equalsIgnoreCase(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG)){
                    firstActivityFlag = "1";
                }
            }
        }
        //"RETURN_FLAG_Activity_001": true 标识驳回到发起环节
        if(("1").equals(returnFlag)){
            //驳回。流程需要配置退回到发起节点
            entity.setFlowStatus(QmsCommonConstant.REJECTED);
            entity.setSignatureInfo("");
        }else if("4".equals(PROCESS_STATUS)){
            //作废
            entity.setFlowStatus(QmsCommonConstant.VOID);
            entity.setSignatureInfo("");
        }else if("1".equals(PROCESS_STATUS)){
            //通过
            assembleSignature(currentActivityId, entity);
            if("1".equals(firstActivityFlag))
                entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);    //驳回后重新提交
            if("1".equals(lastActivityFlag))
                entity.setFlowStatus(QmsCommonConstant.COMPLETED);      //结束审批
        }

        supplierEvaluationMapper.updateById(entity);

//        try {
//            reportDocumentAssistService.updateDocFileAndCreateIWorkflow( variables, entity);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        JSONObject ret = new JSONObject();
        return CommonResult.success(ret);
    }

    private void assembleSignature(String currentActivityId, SupplierEvaluationDO entity){
        if(ObjectUtils.isEmpty(currentActivityId) || "null".equals(currentActivityId))
            return;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sign = entity.getSignatureInfo();
        JSONObject signObj = new JSONObject();
        if(!ObjectUtils.isEmpty( sign))
            signObj = JSONObject.parseObject(sign);
        if(signObj.containsKey(currentActivityId))
            return;
        JSONObject obj = new JSONObject();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Long userId = loginUser.getId();
        //当前登录用户昵称
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        ConfigUserSignatureDO configUserSignatureDO = configUserSignatureService.getByUserId(userId);
        obj.put("signatureId", "");
        if(configUserSignatureDO != null)
            obj.put("signatureId", configUserSignatureDO.getId());
        obj.put("userId", userId);
        obj.put("userName", nickName);
        obj.put("signTime", sdf.format(new Date()));
        signObj.put(currentActivityId, obj);
        entity.setSignatureInfo(signObj.toJSONString());
    }
}