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

import cn.hutool.core.collection.CollectionUtil;
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.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.supplierprocurementplan.BpmOASupplierProcurementPlanPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.supplierprocurementplan.BpmOASupplierProcurementPlanReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.supplierprocurementplan.BpmOASupplierProcurementPlanSaveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.supplierprocurementplan.TheArrivalFileItemsVO;
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOASupplierProcurementPlanItemConvert;
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.mysql.oa.BpmOASupplierProcurementPlanItemMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASupplierProcurementPlanMapper;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.system.api.assets.AssetsApi;
import cn.iocoder.yudao.module.system.api.assets.dto.SupplierAssetAllocationDTO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

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

/**
 * 供应商采购计划 Service 实现类
 *
 * @author 艾楷
 */
@Service
@Validated
public class BpmOASupplierProcurementPlanServiceImpl extends BpmOABaseService implements BpmOASupplierProcurementPlanService {

    @Resource
    private BpmOASupplierProcurementPlanMapper oaSupplierProcurementPlanMapper;
    @Resource
    private BpmOASupplierProcurementPlanItemMapper oaSupplierProcurementPlanItemMapper;
    @Resource
    private BpmOASupplierProcurementPlanItemService supplierProcurementPlanItemService;

    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private BpmHistoryProcessInstanceService historyProcessInstanceService;
    @Resource
    private AssetsApi assetsApi;
    @Resource
    private DeptApi deptApi;

//    @Resource
//    private BpmProcessInstanceService processInstanceService;

    /**
     * OA 供应商资产采购申请 KEY
     */
    public static final String PROCESS_KEY = "oa_gys_procurement_plan_2";

    @Override
    public Long createOaSupplierProcurementPlan(BpmOASupplierProcurementPlanSaveReqVO createReqVO) {
        // 插入
        Long userId = WebFrameworkUtils.getLoginUserId();
        createReqVO.setUserId(userId);
        BpmOASupplierProcurementPlanDO oaSupplierProcurementPlan = BeanUtils.toBean(createReqVO, BpmOASupplierProcurementPlanDO.class);
        oaSupplierProcurementPlanMapper.insert(oaSupplierProcurementPlan);

        // 子列表转换
        List<BpmOASupplierProcurementPlanItemDO> items = BpmOASupplierProcurementPlanItemConvert.INSTANCE.convert(createReqVO.getItems());
        for (BpmOASupplierProcurementPlanItemDO item : items) {
            item.setProcurementPlanId(oaSupplierProcurementPlan.getId());
            item.setUserId(userId);
        }
        oaSupplierProcurementPlanItemMapper.insertBatch(items);
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(userId,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(oaSupplierProcurementPlan.getId()))).getCheckedData();

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

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

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

    @Override
    public void updateOaSupplierProcurementPlan(BpmOASupplierProcurementPlanSaveReqVO updateReqVO) {
        // 更新
        BpmOASupplierProcurementPlanDO updateObj = BeanUtils.toBean(updateReqVO, BpmOASupplierProcurementPlanDO.class);
        oaSupplierProcurementPlanMapper.updateById(updateObj);
    }

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


    @Override
    public BpmOASupplierProcurementPlanDO getOaSupplierProcurementPlan(Long id) {
        return oaSupplierProcurementPlanMapper.selectById(id);
    }

    @Override
    public PageResult<BpmOASupplierProcurementPlanDO> getOaSupplierProcurementPlanPage(BpmOASupplierProcurementPlanPageReqVO pageReqVO) {
        return oaSupplierProcurementPlanMapper.selectPage(pageReqVO);
    }

    @Override
    public void updateSupplierProcurementPlanResult(String processInstanceId, Long id, Integer result) {
        oaSupplierProcurementPlanMapper.updateById(new BpmOASupplierProcurementPlanDO().setId(id).setResult(result).setProcessInstanceId(processInstanceId));
    }

    @Override
    public void batchEditSettlementFlag(List<Long> ids, Integer settlementFlag) {
        oaSupplierProcurementPlanMapper.update(new BpmOASupplierProcurementPlanDO().setSettlementFlag(settlementFlag),
                new LambdaQueryWrapper<BpmOASupplierProcurementPlanDO>()
                        .in(BpmOASupplierProcurementPlanDO::getId, ids));
    }

    @Override
    public List<BpmOASupplierProcurementPlanDO> getListBySupplierId(BpmOASupplierProcurementPlanReqVO vo) {
        List<BpmOASupplierProcurementPlanDO> planDOS = oaSupplierProcurementPlanMapper.selectList(new LambdaQueryWrapper<BpmOASupplierProcurementPlanDO>()
                .eq(vo.getSupplierId() != null, BpmOASupplierProcurementPlanDO::getSupplierId, vo.getSupplierId())
                .gt(vo.getBeginTime() != null, BpmOASupplierProcurementPlanDO::getCreateTime, vo.getBeginTime())
                .le(vo.getEndTime() != null, BpmOASupplierProcurementPlanDO::getCreateTime, vo.getEndTime())
                .eq(vo.getProcessInstanceId() != null, BpmOASupplierProcurementPlanDO::getProcessInstanceId, vo.getProcessInstanceId())
                .eq(vo.getSettlementFlag() != null, BpmOASupplierProcurementPlanDO::getSettlementFlag, vo.getSettlementFlag())
        );
        if (CollectionUtil.isNotEmpty(planDOS)) {
            List<Long> planIds = planDOS.stream().map(BpmOASupplierProcurementPlanDO::getId).collect(Collectors.toList());
            //获取到采购计划详情列表
            List<BpmOASupplierProcurementPlanItemDO> supplierProcurementPlanItemDOS = oaSupplierProcurementPlanItemMapper.selectList(
                    new LambdaQueryWrapper<BpmOASupplierProcurementPlanItemDO>().in(BpmOASupplierProcurementPlanItemDO::getProcurementPlanId, planIds));
            Map<Long, List<BpmOASupplierProcurementPlanItemDO>> map = supplierProcurementPlanItemDOS.stream().collect(Collectors.groupingBy(BpmOASupplierProcurementPlanItemDO::getProcurementPlanId));
            for (BpmOASupplierProcurementPlanDO planDO : planDOS) {
                planDO.setItems(map.get(planDO.getId()));
            }
        }
        return planDOS;
    }

    @Override
    public void uploadDeliveryReceipt(TheArrivalFileItemsVO vo) {
        BpmOASupplierProcurementPlanDO supplierProcurementPlanDO = oaSupplierProcurementPlanMapper.selectById(vo.getId());
        //判断是否需要更新到资产
        boolean updateAssetFlag = false;
        if (supplierProcurementPlanDO.getAssignedFlag() == 0) {
            updateAssetFlag = true;
        }
        supplierProcurementPlanDO.setAssignedFlag(1);
        supplierProcurementPlanDO.setTheArrivalFileItems(vo.getTheArrivalFileItems());
        oaSupplierProcurementPlanMapper.updateById(supplierProcurementPlanDO);
        // ----- 如果需要更新到资产 -
        if (updateAssetFlag) {
            List<BpmOASupplierProcurementPlanItemDO> itemDOS = supplierProcurementPlanItemService.getByProcurementPlanId(vo.getId());
            // 新增资产 + 分配资产
            List<SupplierAssetAllocationDTO> dtos = new ArrayList<>();
            // -- 根据工厂ids 获取部门ids
            CommonResult<Map<Long, Long>> mapCommonResult = deptApi.getDeptListByFactoryIds(itemDOS.stream().map(BpmOASupplierProcurementPlanItemDO::getFactoryId).collect(Collectors.toList()));
            Map<Long, Long> map = mapCommonResult.getCheckedData();
            for (BpmOASupplierProcurementPlanItemDO itemDO : itemDOS) {
                SupplierAssetAllocationDTO dto = new SupplierAssetAllocationDTO();
                dto.setName(itemDO.getSupplierProductName())
                        .setAmount(itemDO.getActualPrice())
                        .setTypeId(itemDO.getTypeId())
                        .setNum(itemDO.getNum())
                        .setInDeptId(map.get(itemDO.getFactoryId()));
                dtos.add(dto);
            }
            assetsApi.supplierAssetAllocation(dtos);
        }
    }

}
