package cn.iocoder.yudao.module.bpm.service.oa;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.supplierpurchasepayment.BpmOASupplierPurchasePaymentPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.supplierpurchasepayment.BpmOASupplierPurchasePaymentSaveReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASupplierProcurementPlanDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASupplierProcurementPlanItemDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASupplierPurchasePaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASupplierProcurementPlanItemMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASupplierProcurementPlanMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASupplierPurchasePaymentMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.system.api.supplier.SupplierApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 供应商采购付款 Service 实现类
 *
 * @author 艾楷
 */
@Service
@Validated
public class BpmOASupplierPurchasePaymentServiceImpl extends BpmOABaseService implements BpmOASupplierPurchasePaymentService {

    @Resource
    private BpmOASupplierPurchasePaymentMapper supplierPurchasePaymentMapper;
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    @Lazy // 解决循环依赖
    private BpmHistoryProcessInstanceService historyProcessInstanceService;
    @Resource
    private BpmProcessInstanceService processInstanceService;
    @Resource
    private BpmOASupplierProcurementPlanService supplierProcurementPlanService;
    @Resource
    private FinancialPaymentService financialPaymentService;
    @Resource
    private AdminUserApi userApi;
    @Resource
    private BpmOASupplierProcurementPlanMapper supplierProcurementPlanMapper;
    @Resource
    private BpmOASupplierProcurementPlanItemMapper supplierProcurementPlanItemMapper;
    @Resource
    private SupplierApi supplierApi;

    /**
     * 供应商采购支付
     */
    public static final String PROCESS_KEY = "oa_supplier_pay_2";

    @Override
    public Long createOASupplierPurchasePayment(BpmOASupplierPurchasePaymentSaveReqVO createReqVO) {
        // 插入
        Long userId = WebFrameworkUtils.getLoginUserId();
        BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = BeanUtils.toBean(createReqVO, BpmOASupplierPurchasePaymentDO.class);
        supplierPurchasePaymentMapper.insert(supplierPurchasePaymentDO);

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(userId,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(supplierPurchasePaymentDO.getId()))).getCheckedData();

        // 将工作流的编号，更新到 OA 采购单中
        supplierPurchasePaymentMapper.updateById(new BpmOASupplierPurchasePaymentDO().setId(supplierPurchasePaymentDO.getId()).setProcessInstanceId(processInstanceId));

        // 判断是否为重新发起的流程
        if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {
            historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
        }

        List<UploadUserFile> fileItems = createReqVO.getFileItems();
        //这里的逻辑，如果fileItems不为空，且有数据，那么说明是上传了附件的，则需要更工作流文件表对应的实例Id
        if (fileItems != null && !fileItems.isEmpty()) {
            uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
        }
        // 返回
        return supplierPurchasePaymentDO.getId();
    }

    @Override
    public void updateOASupplierPurchasePayment(BpmOASupplierPurchasePaymentSaveReqVO updateReqVO) {
        // 更新
        BpmOASupplierPurchasePaymentDO updateObj = BeanUtils.toBean(updateReqVO, BpmOASupplierPurchasePaymentDO.class);
        supplierPurchasePaymentMapper.updateById(updateObj);
    }

    @Override
    public void deleteOASupplierPurchasePayment(Long id) {
        // 删除
        supplierPurchasePaymentMapper.deleteById(id);
    }

    @Override
    public BpmOASupplierPurchasePaymentDO getOASupplierPurchasePayment(Long id) {
        BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = supplierPurchasePaymentMapper.selectById(id);
        // 根据supplierId 供应商id查询供应商
        CommonResult<String> result = supplierApi.getNameById(supplierPurchasePaymentDO.getSupplierId());
        supplierPurchasePaymentDO.setSupplierName(result.getData());
        List<Long> supplierProcurementPlanIds = Arrays.stream(supplierPurchasePaymentDO.getSupplierProcurementPlanIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
        List<BpmOASupplierProcurementPlanDO> planDOS = supplierProcurementPlanMapper.selectList(new LambdaQueryWrapper<BpmOASupplierProcurementPlanDO>().in(BpmOASupplierProcurementPlanDO::getId, supplierProcurementPlanIds));
        List<BpmOASupplierProcurementPlanItemDO> planItemDOS = supplierProcurementPlanItemMapper.selectList(new LambdaQueryWrapper<BpmOASupplierProcurementPlanItemDO>().in(BpmOASupplierProcurementPlanItemDO::getProcurementPlanId, supplierProcurementPlanIds));
        Map<Long, List<BpmOASupplierProcurementPlanItemDO>> itemMap = planItemDOS.stream().collect(Collectors.groupingBy(BpmOASupplierProcurementPlanItemDO::getProcurementPlanId));
        for (BpmOASupplierProcurementPlanDO planDO : planDOS) {
            planDO.setItems(itemMap.get(planDO.getId()));
        }
        supplierPurchasePaymentDO.setSupplierProcurementPlans(planDOS);
        return supplierPurchasePaymentDO;
    }

    @Override
    public PageResult<BpmOASupplierPurchasePaymentDO> getOASupplierPurchasePaymentPage(BpmOASupplierPurchasePaymentPageReqVO pageReqVO) {
        IPage<BpmOASupplierPurchasePaymentDO> assetsDOIPage = supplierPurchasePaymentMapper.getOASupplierPurchasePaymentPage(pageReqVO, MyBatisUtils.buildPage(pageReqVO));
        return new PageResult<>(assetsDOIPage.getRecords(), assetsDOIPage.getTotal());
    }

    @Override
    public void updateSupplierPurchasePaymentResult(String processInstanceId, Long id, Integer result) {
        //审核通过 （最后节点）
        if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
            ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);
            if (instance.isEnded()) {
                // -- 获取到供应商和商品的信息 - 插入到具体到业务表中
                BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = supplierPurchasePaymentMapper.selectById(id);
                List<Long> supplierProcurementPlanIds = Arrays.stream(supplierPurchasePaymentDO.getSupplierProcurementPlanIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
                // -- 批量更新结算方式
                supplierProcurementPlanService.batchEditSettlementFlag(supplierProcurementPlanIds, 1);
                CommonResult<AdminUserRespDTO> user = userApi.getUser(supplierPurchasePaymentDO.getUserId());
                BpmProcessInstanceExtDO processInstance = processInstanceService.getProcessInstanceDO(processInstanceId);
                // -- 插入到财务支付表中
                financialPaymentService.save(new FinancialPaymentDO()
                        .setUserId(supplierPurchasePaymentDO.getUserId())
                        .setDeptId(user.getData() == null ? null : user.getData().getDeptId())
                        .setProcessInstanceId(supplierPurchasePaymentDO.getProcessInstanceId())
                        .setReason(supplierPurchasePaymentDO.getRemark())
                        .setObjectId(id)
                        .setType(5)
                        .setStatus(0)
                        .setAmountPayable(supplierPurchasePaymentDO.getTotalMoney())
                        .setProcessInstanceName(processInstance.getName())
                        .setBeginTime(processInstance.getCreateTime())
                        .setEndTime(processInstance.getEndTime())
                );
            }
        }
        supplierPurchasePaymentMapper.updateById(new BpmOASupplierPurchasePaymentDO().setId(id).setResult(result).setProcessInstanceId(processInstanceId));
    }

}
