package com.jwipc.inquiry.logic.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.constant.DictCode;
import com.jwipc.inquiry.convert.PurchaseApplyBillApiConvert;
import com.jwipc.inquiry.dto.PurchaseApplyBillApiDTO;
import com.jwipc.inquiry.dto.PurchaseApplyBillDetailApiDTO;
import com.jwipc.inquiry.dto.ShareProjectApplyApiDTO;
import com.jwipc.inquiry.dto.ShareProjectApplyDetailApiDTO;
import com.jwipc.inquiry.entity.PurchaseApplyBill;
import com.jwipc.inquiry.entity.PurchaseApplyBillDetail;
import com.jwipc.inquiry.logic.PurchaseApplyBillApiLogic;
import com.jwipc.inquiry.service.IPurchaseApplyBillDetailService;
import com.jwipc.inquiry.service.IPurchaseApplyBillService;
import com.jwipc.sys.client.*;
import com.jwipc.sys.client.dto.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2024/3/27 12:32
 * @desc
 */
@Service
@RequiredArgsConstructor
public class PurchaseApplyBillApiLogicImpl implements PurchaseApplyBillApiLogic {
    private final PurchaseApplyBillApiConvert purchaseApplyBillApiConvert;
    private final IPurchaseApplyBillService purchaseApplyBillService;
    private final IPurchaseApplyBillDetailService purchaseApplyBillDetailService;
    private final DictClient dictClient;
    private final FactoryClient factoryClient;
    private final ProductClient productClient;
    private final ProductGroupClient productGroupClient;
    private final PurchaseGroupClient purchaseGroupClient;
    private final UserClient userClient;
    @Override
    @Transactional
    public ApiResult sync(List<PurchaseApplyBillApiDTO> param) {

        //采购申请类型
        List<DictDTO> applyTypes = dictClient.getDicByType(DictCode.APPLY_TYPE.getCode());
        final Map<String, DictDTO> applyTypeCache = applyTypes.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
        final Set<String> applyTypeCodes = applyTypeCache.keySet();

        //工厂
        final List<FactoryDTO> all = factoryClient.getAll();
        final Map<String, FactoryDTO> factoryCache = all.stream()
                .collect(Collectors.toMap(FactoryDTO::getFactory, a -> a));
        final Set<String> factoryCodes = factoryCache.keySet();

        //物料组
        List<ProductGroupDTO> productGroupDTOS = productGroupClient.getAll();
        productGroupDTOS = productGroupDTOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
                -> new TreeSet<>(Comparator.comparing(ProductGroupDTO::getMaterialGroup))), ArrayList::new));
        final Map<String, ProductGroupDTO> productGroupCache = productGroupDTOS.stream()
                .collect(Collectors.toMap(ProductGroupDTO::getMaterialGroup, a -> a));
        final Set<String> productGroupCodes = productGroupCache.keySet();

        //采购组
        final List<PurchaseGroupDTO> purchaseGroupDTOS = purchaseGroupClient.getAll();
        final Map<String, PurchaseGroupDTO> purchaseGroupCache = purchaseGroupDTOS.stream()
                .collect(Collectors.toMap(PurchaseGroupDTO::getPurchaseGroupCode, a -> a));
        final Set<String> purchaseGroupCodes = purchaseGroupCache.keySet();
        try {
            for (PurchaseApplyBillApiDTO purchaseApplyBillApiDTO : param){
                if (!applyTypeCodes.contains(purchaseApplyBillApiDTO.getApplyTypeCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("采购申请类型编码：{}在系统中不存在",purchaseApplyBillApiDTO.getApplyTypeCode())).build();
                }
                PurchaseApplyBill purchaseApplyBill = purchaseApplyBillService.getOne(Wrappers.lambdaQuery(PurchaseApplyBill.class)
                        .eq(PurchaseApplyBill::getBillCode,purchaseApplyBillApiDTO.getBillCode()).last(" limit 1"));
                PurchaseApplyBill bill = purchaseApplyBillApiConvert.dto2Entity(purchaseApplyBillApiDTO);
                bill.setApplyTime(LocalDateTimeUtil.parse(purchaseApplyBillApiDTO.getApplyTimeStr(),"yyyy-MM-dd HH:mm:ss"));
                if (ObjectUtil.isNull(purchaseApplyBill)){
                    bill.setStatus(1);
                    bill.setCreateTime(LocalDateTime.now());
                }else {
                    bill.setId(purchaseApplyBill.getId());
                    bill.setUpdateTime(LocalDateTime.now());
                }
                bill.setPurchaseApplyTypeCode(purchaseApplyBillApiDTO.getApplyTypeCode());
                purchaseApplyBillService.saveOrUpdate(bill);

                //明细
                List<PurchaseApplyBillDetailApiDTO> detailDTOS = purchaseApplyBillApiDTO.getItem();
                List<PurchaseApplyBillDetail> needSaveOrUpdate = new ArrayList<>();
                for (PurchaseApplyBillDetailApiDTO detail : detailDTOS){
                    if (StringUtils.isNotEmpty(detail.getFactoryCode())&&!factoryCodes.contains(detail.getFactoryCode())){
                        return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("工厂编码：{}在系统中不存在",detail.getFactoryCode())).build();
                    }
                    if (StringUtils.isNotEmpty(detail.getPurchaseGroupCode())&&!purchaseGroupCodes.contains(detail.getPurchaseGroupCode())){
                        return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("采购组：{}在系统中不存在",detail.getPurchaseGroupCode())).build();
                    }
                    if (StringUtils.isNotEmpty(detail.getMaterialGroupCode())&&!productGroupCodes.contains(detail.getMaterialGroupCode())){
                        return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("物料组：{}在系统中不存在",detail.getMaterialGroupCode())).build();
                    }
                    PurchaseApplyBillDetail billDetail = purchaseApplyBillApiConvert.DetailDto2Entity(detail);
                    billDetail.setBillId(bill.getId().toString());
                    billDetail.setBillCode(bill.getBillCode());
                    billDetail.setDetailRemark(detail.getItemRemark());
                    billDetail.setCustomerCode(detail.getCustomerCode());
                    billDetail.setCustomerName(detail.getCustomerName());
                    billDetail.setUnitCode(detail.getUnitCodeBase());
                    billDetail.setFactor(detail.getFactor());
                    billDetail.setPrice(detail.getPrice());
                    billDetail.setTeamName(detail.getTeamName());
                    billDetail.setTotalAmount(detail.getTotalPrice());
                    billDetail.setPrice(detail.getPrice());
                    ProductGroupDTO productGroupDTO = productGroupCache.get(detail.getMaterialGroupCode());
                    billDetail.setMaterialGroupName(productGroupDTO.getMaterialDesc());
                    if (StringUtils.isNotEmpty(detail.getMaterialCode())&&StringUtils.isNotEmpty(detail.getFactoryCode())){
                        ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(detail.getMaterialCode(),detail.getFactoryCode());
                        billDetail.setUnitCode(Optional.ofNullable(productInfoDTO).map(ProductInfoDTO::getOrderUnit).orElse(billDetail.getUnitCodeBase()));
                    }
                    billDetail.setRequireNum(billDetail.getApprovalNumber());
                    billDetail.setRequireNumBase(billDetail.getApprovalNumber());
                    //采购申请数据创建时给剩余数量字段塞值供商城使用
                    billDetail.setRemainQuantity(billDetail.getRequireNum());

                    PurchaseApplyBillDetail oldDetail = purchaseApplyBillDetailService.getOne(Wrappers.lambdaQuery(PurchaseApplyBillDetail.class)
                            .eq(PurchaseApplyBillDetail::getBillCode,bill.getBillCode())
                            .eq(PurchaseApplyBillDetail::getItemCode,detail.getItemCode()).last(" limit 1"));
                    if (ObjectUtil.isNotNull(oldDetail)){
                        billDetail.setId(oldDetail.getId());
                        billDetail.setDataState(1);
                    }else {
                        billDetail.setDataState(0);
                    }
                    needSaveOrUpdate.add(billDetail);
                }
                purchaseApplyBillDetailService.saveOrUpdateBatch(needSaveOrUpdate);
            }
        }catch (Exception e){
            e.printStackTrace();
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(e.getMessage()).build();
        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).message("成功").build();
    }

    /**
     * 接收共享立项申请单数据保存到SRM采购申请单
     * @param param 共享立项申请单DTO
     * @return 处理结果
     */
    @Override
    public ApiResult saveFromShare(ShareProjectApplyApiDTO param) {
        //采购组
        final List<PurchaseGroupDTO> purchaseGroupDTOS = purchaseGroupClient.getAll();
        final Map<String, PurchaseGroupDTO> purchaseGroupCache = purchaseGroupDTOS.stream()
                .collect(Collectors.toMap(PurchaseGroupDTO::getPurchaseGroupCode, a -> a));
        final Set<String> purchaseGroupCodes = purchaseGroupCache.keySet();
        try {
            // 基础信息
            PurchaseApplyBill bill = new PurchaseApplyBill();
            PurchaseApplyBill purchaseApplyBill = purchaseApplyBillService.getOne(Wrappers.lambdaQuery(PurchaseApplyBill.class)
                    .eq(PurchaseApplyBill::getBillCode,param.getBillCode()).last(" limit 1"));
            if (ObjectUtil.isNull(purchaseApplyBill)){
                bill.setStatus(1);
                bill.setCreateTime(LocalDateTime.now());
            }else {
                bill.setId(purchaseApplyBill.getId());
                bill.setUpdateTime(LocalDateTime.now());
            }
            bill.setSource(3);
            //传值”02" 01：费用类（共享立项单） 02：资产类
            bill.setPurchasingBusinessType(param.getPurchasingBusinessType());
            bill.setBillCode(param.getBillCode());
            bill.setCompanyCode(param.getCompanyCode());
            //申请人工号
            bill.setCreateUserCode(param.getApplyUserCode());
            if (StringUtils.isEmpty(param.getApplyUserCode())) {
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("申请人工号不能为空")).build();
            }
            bill.setCreateUserName(param.getApplyUserName());
            //资产申请单据类型
            bill.setApplyBillType(param.getApplyBillType());
            UserDTO createUser = userClient.getByUserCodeOrName(param.getApplyUserCode(), param.getApplyUserName());
            if (createUser != null) {
                bill.setCreateUser(createUser.getId());
            }
//            else {
//                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("申请人工号：{}在系统中不存在",param.getApplyUserCode())).build();
//            }
            bill.setApplyDeptName(param.getApplyDeptName());
            bill.setApplyTime(LocalDateTimeUtil.parse(param.getApplyTimeStr(),"yyyy-MM-dd HH:mm:ss"));
            //主要用途
            bill.setMainUses(param.getMainUses());
            bill.setCurrency(param.getCurrency());
//            bill.setRemark( param.getRemark());
            if (StringUtils.isNotEmpty(bill.getPurchasingBusinessType()) && bill.getPurchasingBusinessType().equals("02")) {
                //采购申请类型
                List<DictDTO> applyTypes = dictClient.getDicByType(DictCode.APPLY_TYPE.getCode());
                final Map<String, DictDTO> applyTypeCache = applyTypes.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
                final Set<String> applyTypeCodes = applyTypeCache.keySet();
                //采购申请类型编码（采购类别	）	applyTypeCode 校验
                if (!applyTypeCodes.contains(param.getApplyTypeCode())){
//                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("采购申请类型编码：{}在系统中不存在",param.getApplyTypeCode())).build();
                }
                //费用类不传；资产： 01办公用品  02资产
                bill.setPurchaseApplyTypeCode(param.getApplyTypeCode());
                //采购组校验
                if (StringUtils.isNotEmpty(param.getPurchaseGroupCode())&&!purchaseGroupCodes.contains(param.getPurchaseGroupCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("采购组：{}在系统中不存在",param.getPurchaseGroupCode())).build();
                }
                bill.setPurchaseGroupCode(param.getPurchaseGroupCode());
                //存放地点
                bill.setStockPoint(param.getStockPoint());
                //采购类别1、传编码 2、编码规则： 01 | 办公用品 02 | 资产  3、资产包括：低耗、IT电脑及周边、机器设备、生产治具、模具、软件、在建工程、设备类租赁及维修
                bill.setProcureSubclass(param.getProcureSubclass());
                //申请样品制作项目类型 模具: 01-钣金件 02-散热 03-塑胶件 04-其他 05	铝壳/铝件
                bill.setApplyProjectType(param.getApplyProjectType());
                //模具申请模具: 01 | 手板 02 | 开模 03 | 修模
                bill.setModelApply(param.getModelApply());
                //项目所处阶段
                bill.setProjectProcess(param.getProjectProcess());

                bill.setProjectNo(param.getProjectNo());
                bill.setProjectName(param.getProjectName());

            }

            purchaseApplyBillService.saveOrUpdate(bill);
            // 明细
            List<PurchaseApplyBillDetail> needSaveOrUpdate = new ArrayList<>();
            for (ShareProjectApplyDetailApiDTO item : param.getDetails()) {
                PurchaseApplyBillDetail newDetail = new PurchaseApplyBillDetail();
                newDetail.setBillId(bill.getId().toString());
                newDetail.setBillCode(bill.getBillCode());
                if (StringUtils.isEmpty(item.getItemCode())){
                    //采购申请的行编号（明细序号） 必填
                    return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【采购申请的行编号（明细序号）】不能为空").build();
                }
                newDetail.setItemCode(item.getItemCode());
                newDetail.setMaterialName(item.getMaterialName());
                newDetail.setMaterialCode(item.getMaterialCode());
                if (StringUtils.equals(bill.getPurchasingBusinessType(), "01")) {
                    if (StringUtils.isEmpty(item.getExpenseTypeCode())){
                        //费用类 报销类别-编码 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【报销类别-编码】不能为空").build();
                    }
                    if (StringUtils.isEmpty(item.getExpenseTypeLongName())){
                        //费用类 报销类别-长名称 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【报销类别-长名称】不能为空").build();
                    }
                    if (StringUtils.isEmpty(item.getCostUndertakeDeptCode())){
                        //费用类 费用承担部门编码 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【费用承担部门编码】不能为空").build();
                    }
                    if (StringUtils.isEmpty(item.getCostUndertakeDeptName())){
                        //费用类 费用承担部门名称 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【费用承担部门名称】不能为空").build();
                    }
                    if (StringUtils.isEmpty(item.getCostCenterCode())){
                        //费用类 成本中心编码 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【成本中心编码】不能为空").build();
                    }
                    if (StringUtils.isEmpty(item.getCostCenterName())){
                        //费用类 成本中心名称 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【成本中心名称】不能为空").build();
                    }
                    newDetail.setMaterialName(item.getMaterialSpec());
                    newDetail.setMaterialGroupCode("Z99002");
                    newDetail.setMaterialGroupName("费用性物料");
                } else if (StringUtils.isNotEmpty(bill.getPurchasingBusinessType()) && bill.getPurchasingBusinessType().equals("02")) {
                    //采购申请类型
                    if (StringUtils.isEmpty(item.getMaterialName())){
                        //费用类 物料描述（短描述）- 物品名称 必填
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("明细字段【物品名称】不能为空").build();
                    }
                    newDetail.setMaterialName(item.getMaterialName());
                    newDetail.setMaterialGroupCode("Z99001");
                    newDetail.setMaterialGroupName("固定资产物料");
                }
                //报销类别-长名称
                newDetail.setExpenseTypeCode(item.getExpenseTypeCode());
                newDetail.setExpenseTypeLongName(item.getExpenseTypeLongName());
                newDetail.setMaterialSpec(item.getMaterialSpec());
                newDetail.setCostUndertakeDeptName(item.getCostUndertakeDeptName());
                newDetail.setCostUndertakeDeptCode(item.getCostUndertakeDeptCode());
                //审批通过数量
                BigDecimal approvalNumber = item.getApprovalNumber() == null ? BigDecimal.ONE : item.getApprovalNumber();
                newDetail.setApprovalNumber(approvalNumber);
                //需求数量
                newDetail.setRequireNum(approvalNumber);
                newDetail.setRequireNumBase(approvalNumber);
                //剩余数量
                newDetail.setRemainQuantity(approvalNumber);

                if (StringUtils.isNotEmpty(item.getUnitCodeBase())) {
                    newDetail.setUnitCodeBase(item.getUnitCodeBase());
                } else {
                    newDetail.setUnitCodeBase("PCS");
                }
                newDetail.setUnitCode(newDetail.getUnitCodeBase());
                newDetail.setFactoryCode(param.getCompanyCode());
                newDetail.setPrice(item.getPrice());
                if (StringUtils.isNotEmpty(param.getPurchaseGroupCode())&&!purchaseGroupCodes.contains(param.getPurchaseGroupCode())){
                    return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message(StrUtil.format("采购组：{}在系统中不存在",param.getPurchaseGroupCode())).build();
                }
                newDetail.setPurchaseGroupCode(param.getPurchaseGroupCode());
                //品牌
                newDetail.setBrand(item.getBrand());
                //customerCode
                newDetail.setCustomerCode(item.getCustomerCode());
                //customerName
                newDetail.setCustomerName(item.getCustomerName());
                //采购细类 传编码
                newDetail.setSubjectTypeCode(item.getSubjectTypeCode());
                //预计使用年限 传编码
                newDetail.setExpiredServiceYear(item.getExpiredServiceYear());
                //使用人员工号
                newDetail.setUserCode(item.getUserCode());
                //使用人员姓名
                newDetail.setUserName(item.getUserName());
                //使用部门编码
                newDetail.setUseDeptCode(item.getUseDeptCode());
                //使用部门名称
                newDetail.setUseDeptName(item.getUseDeptName());
                //采购路径 传编码
                newDetail.setPurchaseWay(item.getPurchaseMethod());
                //采购方式默认 Z005 未转
                if (StringUtils.isNotEmpty(bill.getPurchasingBusinessType()) && bill.getPurchasingBusinessType().equals("02")) {
                    newDetail.setPurchaseMethod("Z005");
                }
                //申请金额  合计金额(资产申请明细“合计金额”)
                newDetail.setTotalAmount(item.getTotalAmount());
                //模具类型
                newDetail.setModelType(item.getModelType());
                //模具编码
                newDetail.setModelNumber(item.getModelNumber());

                //备注
                newDetail.setDetailRemark(item.getItemRemark());
                //成本中心
                newDetail.setCostCenterCode(item.getCostCenterCode());
                //成本中心描述
                newDetail.setCostCenterName(item.getCostCenterName());


                if (StringUtils.isNotEmpty(bill.getApplyBillType()) && bill.getApplyBillType().equals("fa_asset_apply_mj")) {
                    if(StringUtils.isEmpty(item.getSupplierCode())){
                        return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message("模具类型的明细字段【供应商代码】不能为空").build();
                    }else{
                        newDetail.setSupplierCode(item.getSupplierCode());
                    }
                }
                PurchaseApplyBillDetail oldDetail = purchaseApplyBillDetailService.getOne(Wrappers.lambdaQuery(PurchaseApplyBillDetail.class)
                        .eq(PurchaseApplyBillDetail::getBillCode,bill.getBillCode())
                        .eq(PurchaseApplyBillDetail::getItemCode,item.getItemCode()).last(" limit 1"));
                if (ObjectUtil.isNotNull(oldDetail)){
                    newDetail.setId(oldDetail.getId());
                    newDetail.setDataState(1);
                }else {
                    newDetail.setDataState(0);
                }
                needSaveOrUpdate.add(newDetail);
            }
            purchaseApplyBillDetailService.saveOrUpdateBatch(needSaveOrUpdate);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResult.builder().code(RestCode.SHARE_ERROR.getCode()).message(e.getMessage()).build();
        }
        return ApiResult.builder().code(RestCode.SHARE_SUCCESS.getCode()).message("成功").build();
    }
}
