package com.zt.plat.module.qms.business.bus.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.qms.api.task.BMPCallbackInterface;
import com.zt.plat.module.qms.api.task.dto.QmsBpmDTO;
import com.zt.plat.module.qms.business.bus.controller.vo.*;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessHandoverRecordSubDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessSampleDispatchDetailDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessSubSampleDO;
import com.zt.plat.module.qms.common.dic.service.DictionaryBusinessService;
import com.zt.plat.module.qms.enums.QmsBpmConstant;
import com.zt.plat.module.qms.enums.QmsCommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

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

import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessSampleDispatchDO;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;

import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessSampleDispatchMapper;

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.module.qms.enums.ErrorCodeConstants.*;
import static com.zt.plat.module.qms.enums.QmsBpmConstant.BPM_CALLBACK_BEAN_NAME;

/**
 * 样品调拨 Service 实现类
 *
 * @author 后台管理
 */
@Service("businessSampleDispatchService")
@Validated
@Slf4j
public class BusinessSampleDispatchServiceImpl implements BusinessSampleDispatchService, BMPCallbackInterface {

    @Resource private BusinessSampleDispatchMapper businessSampleDispatchMapper;
    @Resource private BusinessSampleDispatchDetailService businessSampleDispatchDetailService;
    @Resource private BusinessSubSampleService businessSubSampleService;
    @Resource private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource private BpmTaskApi bpmTaskApi;
    @Resource private DictionaryBusinessService dictionaryBusinessService;
    @Resource private BusinessHandoverRecordSubService businessHandoverRecordSubService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrRemoveSample(BusinessSampleDispatchSaveReqVO paramVo, boolean updateCancelFlag) {
        Long id = paramVo.getId();
        List<Long> addSubSampleIds = paramVo.getAddSubSampleIds();
        List<Long> removeDetailIds = paramVo.getRemoveDetailIds();
        BusinessSampleDispatchDO entity = getBusinessSampleDispatch(id);
        //处理移除
        if(removeDetailIds != null && !removeDetailIds.isEmpty()){
            businessSampleDispatchDetailService.deleteBusinessSampleDispatchDetailListByIds(removeDetailIds);
        }
        //处理新增
        if(addSubSampleIds != null && !addSubSampleIds.isEmpty()){
            List<BusinessSampleDispatchDetailDO> detailList = businessSampleDispatchDetailService.listByParID(id);
            //去除已添加过的
            List<Long> hasIds = detailList.stream().map(BusinessSampleDispatchDetailDO::getBusinessSubSampleId).toList();
            addSubSampleIds.removeAll(hasIds);
            List<BusinessSampleDispatchDetailDO> insertList = new ArrayList<>();
            for (Long subSampleId : addSubSampleIds) {
                BusinessSampleDispatchDetailDO detail = new BusinessSampleDispatchDetailDO();
                detail.setBusinessSubSampleId(subSampleId);
                detail.setParentId(id);
                insertList.add(detail);
            }
            if(!insertList.isEmpty()){
                businessSampleDispatchDetailService.insertBatch(insertList);
                if(updateCancelFlag && "-1".equals(entity.getCancelStatus())){
                    //如果有新增，修改临时数据状态
                    entity.setCancelStatus("0");
                    businessSampleDispatchMapper.updateById(entity);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<BusinessSampleDispatchRespVO> createProcessInstance(BusinessSampleDispatchSaveReqVO param) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        //当前登录用户昵称
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        Long id = param.getId();
        BusinessSampleDispatchDO entity = getBusinessSampleDispatch( id);
        JSONObject formData = new JSONObject();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        entity.setApplyUser(nickName);
        entity.setApplyUserId(loginUser.getId());
        entity.setApplyDepartment(loginUser.getVisitDeptName());
        entity.setApplyDepartmentId(loginUser.getVisitDeptId());
        entity.setApplyTime(LocalDateTime.now());

        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()));
        formData.put("mainDepartmentId",  entity.getMainDepartmentId());
        formData.put("mainDepartmentName",  entity.getMainDepartmentName());
        Map<String, Object> variables = formData.toJavaObject(Map.class);
        variables.put(BPM_CALLBACK_BEAN_NAME, "businessSampleDispatchService"); //流程回调时使用的service
        String dictKey = "qms_sample_dispatch_flow_key";    //todo 创建业务字典
        String flowKey = dictionaryBusinessService.getValueByDataKey(dictKey);
        BpmProcessInstanceCreateReqDTO reqDTO = new BpmProcessInstanceCreateReqDTO();
        reqDTO.setBusinessKey(String.valueOf(id));
        reqDTO.setProcessDefinitionKey(flowKey);
        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);
        businessSampleDispatchMapper.updateById(entity);
        BusinessSampleDispatchRespVO respVO = BeanUtils.toBean(entity, BusinessSampleDispatchRespVO.class);
        return CommonResult.success(respVO);
    }

    /*
    * 执行调拨，传入调拨申请id，将所有明细置为已调拨状态*/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execDispatch(BusinessSampleDispatchSaveReqVO paramVo) {
        Long id = paramVo.getId();

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        String warehouseUser = nickName;      //库管员
        Long warehouseUserId = loginUser.getId();
        BusinessSampleDispatchDO entity = getBusinessSampleDispatch( id);
        BusinessSampleDispatchDetailPageReqVO pageReqVO = new BusinessSampleDispatchDetailPageReqVO();
        pageReqVO.setParentId(id);
        pageReqVO.setPageSize(9999);
        List<BusinessSampleDispatchDetailExtendRespVO> detailList = businessSampleDispatchDetailService.getBusinessSampleDispatchDetailPage(pageReqVO).getList();
        List<BusinessSampleDispatchDetailDO> detailUpdateList = new ArrayList<>();

        LocalDateTime borrowTime = LocalDateTime.now();
        List<BusinessHandoverRecordSubDO> handoverRecordList = new ArrayList<>();
        for (BusinessSampleDispatchDetailExtendRespVO detail : detailList) {
            BusinessSampleDispatchDetailDO u = new BusinessSampleDispatchDetailDO();
            u.setId(detail.getId());
            u.setUseStatus("1");
            u.setBorrowStatus("1");
            u.setGivebackStatus("0");
            u.setBorrowUser(entity.getApplyUser());
            u.setBorrowUserId(entity.getApplyUserId());
            u.setBorrowTime(borrowTime);
            detailUpdateList.add(u);
            //交接记录
            BusinessHandoverRecordSubDO handoverRecord = new BusinessHandoverRecordSubDO();
            handoverRecord.setBusinessSubSampleId(detail.getBusinessSubSampleId());
            handoverRecord.setSampleCode(detail.getSampleCode());
            handoverRecord.setSampleFlowNodeKey(QmsCommonConstant.FLOW_SAMPLE_STORAGE);
            handoverRecord.setOperationTime(borrowTime);
            handoverRecord.setOperator(warehouseUser);
            handoverRecord.setOperatorId(warehouseUserId);
            handoverRecord.setSendSampleOperator(warehouseUser);            //送样人
            handoverRecord.setReceiveSampleOperator(entity.getApplyUser()); //收样人
            handoverRecordList.add(handoverRecord);
        }
        businessSampleDispatchDetailService.updateBatch(detailUpdateList);
        businessHandoverRecordSubService.insertBatch(handoverRecordList);
        entity.setFinishStatus(QmsCommonConstant.COMPLETED);
        entity.setWarehouseUser(warehouseUser);
        entity.setWarehouseUserId(warehouseUserId);
        businessSampleDispatchMapper.updateById(entity);
        //更新子样状态
        List<Long> subSampleIds = detailList.stream().map(BusinessSampleDispatchDetailExtendRespVO::getBusinessSubSampleId).toList();
        List<BusinessSubSampleDO> subSampleList = businessSubSampleService.listByIdList(subSampleIds);
        for (BusinessSubSampleDO subSample : subSampleList) {
            subSample.setDispatchStatus("1");
        }
        businessSubSampleService.updateBatch(subSampleList);



        return CommonResult.success("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> execGiveback(JSONObject paramVo) {

        String givebackUser = paramVo.getString("givebackUser");        //归还人
        Long givebackUserId = paramVo.getLong("givebackUserId");
        String warehouseUser = paramVo.getString("warehouseUser");      //库管员
        Long warehouseUserId = paramVo.getLong("warehouseUserId");
        String detailIds = paramVo.getString("detailIds");
        List< Long> detailIdList = Arrays.asList(detailIds.split(",")).stream().map(Long::parseLong).toList();
        LocalDateTime givebackTime = LocalDateTime.now();
        BusinessSampleDispatchDetailPageReqVO pageReqVO = new BusinessSampleDispatchDetailPageReqVO();
        pageReqVO.setIdList(detailIdList);
        pageReqVO.setPageSize(detailIdList.size() + 999);
        List<BusinessSampleDispatchDetailExtendRespVO> detailList = businessSampleDispatchDetailService.getBusinessSampleDispatchDetailPage(pageReqVO).getList();
        List<BusinessSampleDispatchDetailDO> detailUpdateList = new ArrayList<>();
        List<BusinessHandoverRecordSubDO> handoverRecordList = new ArrayList<>();
        for (BusinessSampleDispatchDetailExtendRespVO detail : detailList) {
            BusinessSampleDispatchDetailDO u = new BusinessSampleDispatchDetailDO();
            u.setGivebackUser(givebackUser);
            u.setGivebackUserId(givebackUserId);
            u.setGivebackTime(givebackTime);
            u.setGivebackStatus("1");
            u.setId(detail.getId());
            detailUpdateList.add(u);

            //交接记录
            BusinessHandoverRecordSubDO handoverRecord = new BusinessHandoverRecordSubDO();
            handoverRecord.setBusinessSubSampleId(detail.getBusinessSubSampleId());
            handoverRecord.setSampleCode(detail.getSampleCode());
            handoverRecord.setOperationTime(givebackTime);
            handoverRecord.setOperator(givebackUser);
            handoverRecord.setOperatorId(givebackUserId);
            handoverRecord.setSendSampleOperator(givebackUser);            //送样人
            handoverRecord.setReceiveSampleOperator(warehouseUser); //收样人
            handoverRecord.setSampleFlowNodeKey(QmsCommonConstant.FLOW_SAMPLE_STORAGE);
            handoverRecordList.add(handoverRecord);
        }
        businessSampleDispatchDetailService.updateBatch(detailUpdateList);
        businessHandoverRecordSubService.insertBatch(handoverRecordList);
        //更新子样状态
        List<Long> subSampleIds = detailList.stream().map(BusinessSampleDispatchDetailExtendRespVO::getBusinessSubSampleId).toList();
        List<BusinessSubSampleDO> subSampleList = businessSubSampleService.listByIdList(subSampleIds);
        for (BusinessSubSampleDO subSample : subSampleList) {
            subSample.setDispatchStatus("0");
        }
        businessSubSampleService.updateBatch(subSampleList);
        return CommonResult.success("操作成功");
    }

    @Override
    public BusinessSampleDispatchRespVO createBusinessSampleDispatch(BusinessSampleDispatchSaveReqVO createReqVO) {
        BusinessSampleDispatchDO businessSampleDispatch = BeanUtils.toBean(createReqVO, BusinessSampleDispatchDO.class);
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        if(businessSampleDispatch.getApplyUser() == null){
            businessSampleDispatch.setApplyUser(nickName);
            businessSampleDispatch.setApplyUserId(loginUser.getId());
        }

        businessSampleDispatchMapper.insert(businessSampleDispatch);
        // 返回
        return BeanUtils.toBean(businessSampleDispatch, BusinessSampleDispatchRespVO.class);
    }

    @Override
    public void updateBusinessSampleDispatch(BusinessSampleDispatchSaveReqVO updateReqVO) {
        // 校验存在
        validateBusinessSampleDispatchExists(updateReqVO.getId());
        // 更新
        BusinessSampleDispatchDO updateObj = BeanUtils.toBean(updateReqVO, BusinessSampleDispatchDO.class);
        businessSampleDispatchMapper.updateById(updateObj);
    }

    @Override
    public void deleteBusinessSampleDispatch(Long id) {
        // 校验存在
        validateBusinessSampleDispatchExists(id);
        // 删除
        businessSampleDispatchMapper.deleteById(id);
    }

    @Override
        public void deleteBusinessSampleDispatchListByIds(List<Long> ids) {
        // 校验存在
        validateBusinessSampleDispatchExists(ids);
        // 删除
        businessSampleDispatchMapper.deleteByIds(ids);
        }

    private void validateBusinessSampleDispatchExists(List<Long> ids) {
        List<BusinessSampleDispatchDO> list = businessSampleDispatchMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(BUSINESS_SAMPLE_DISPATCH_NOT_EXISTS);
        }
    }

    private void validateBusinessSampleDispatchExists(Long id) {
        if (businessSampleDispatchMapper.selectById(id) == null) {
            throw exception(BUSINESS_SAMPLE_DISPATCH_NOT_EXISTS);
        }
    }

    @Override
    public BusinessSampleDispatchDO getBusinessSampleDispatch(Long id) {
        return businessSampleDispatchMapper.selectById(id);
    }

    @Override
    public PageResult<BusinessSampleDispatchDO> getBusinessSampleDispatchPage(BusinessSampleDispatchPageReqVO pageReqVO) {
        return businessSampleDispatchMapper.selectPage(pageReqVO);
    }

    //流程回调
    @Override
    public CommonResult<JSONObject> callback(QmsBpmDTO reqDTO) {
        JSONObject variables = reqDTO.getVariables();

        //流程状态  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);
        }
        BusinessSampleDispatchDO entity = getBusinessSampleDispatch(Long.valueOf(mainId));
        log.error("流程回调：{}", JSONObject.toJSONString(reqDTO));
        String currentActivityId = variables.getString(QmsBpmConstant.BPM_CALLBACK_ACTIVITY_ID);
        String RETURN_FLAG_PREFIX_KEY = QmsBpmConstant.BPM_CALLBACK_RETURN_FLAG_PREFIX_KEY;
        String returnFlagKey = RETURN_FLAG_PREFIX_KEY + "Activity_001";

        //判断是否最后一个节点
        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").equals(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG)){
                    lastActivityFlag = "1";
                }
                if(fieldExtension.getString("fieldName").equals(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG)){
                    firstActivityFlag = "1";
                }
            }
        }

        //"RETURN_FLAG_Activity_001": true 标识驳回到发起环节
        if(variables.containsKey(returnFlagKey) && variables.getString(returnFlagKey).equals("true")){
            //驳回。流程需要配置退回到发起节点
            entity.setFlowStatus(QmsCommonConstant.REJECTED);
        }else if("4".equals(PROCESS_STATUS)){
            //作废
            entity.setFlowStatus(QmsCommonConstant.VOID);
        }else if("1".equals(PROCESS_STATUS)){
            //通过
            if("1".equals(firstActivityFlag))
                entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS);    //驳回后重新提交
            if("1".equals(lastActivityFlag)){
                entity.setFlowStatus(QmsCommonConstant.COMPLETED);      //结束审批
                entity.setFinishStatus(QmsCommonConstant.PENDING);
            }
        }
        businessSampleDispatchMapper.updateById(entity);
        JSONObject ret = new JSONObject();
        return CommonResult.success(ret);
    }
}