package com.sunxung.factoring.service.cashflowmanage.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.CashFlowEntryTypeDict;
import com.sunxung.factoring.dict.impl.CashFlowOutTypeDict;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.LedgerStatusDict;
import com.sunxung.factoring.entity.GridPage;
import com.sunxung.factoring.entity.ResponseJson;
import com.sunxung.factoring.entity.cashflowmanage.CashFlowManageBasicInfo;
import com.sunxung.factoring.entity.cashflowmanage.CashFlowManageEntryInfo;
import com.sunxung.factoring.entity.cashflowmanage.CashFlowManageOutInfo;
import com.sunxung.factoring.entity.cashflowmanage.request.AddCashFlowRequest;
import com.sunxung.factoring.entity.cashflowmanage.sop.BankAccountInfo;
import com.sunxung.factoring.entity.cashflowmanage.sop.BillingNonbusinessManageFactoringentry;
import com.sunxung.factoring.entity.cashflowmanage.vo.*;
import com.sunxung.factoring.entity.entprise.Enterprise;
import com.sunxung.factoring.entity.financing.apply.CFinancingBasicInfo;
import com.sunxung.factoring.entity.ledger.LedgerAccountBasicInfo;
import com.sunxung.factoring.entity.project.ProjectCoreEnterprise;
import com.sunxung.factoring.entity.supplier.SupplierInfo;
import com.sunxung.factoring.entity.sys.*;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
import com.sunxung.factoring.entity.underlying.sop.BillingFactoringBusinessLoanRecord;
import com.sunxung.factoring.mapper.cashflowmanage.CashFlowManageBaseInfoMapper;
import com.sunxung.factoring.service.cashflowmanage.CashFlowManageBasicInfoService;
import com.sunxung.factoring.service.cashflowmanage.CashFlowManageEntryInfoService;
import com.sunxung.factoring.service.cashflowmanage.CashFlowManageOutInfoService;
import com.sunxung.factoring.service.customerinformation.SupplierBankCardInfoService;
import com.sunxung.factoring.service.entprise.IEnterpriseService;
import com.sunxung.factoring.service.financing.apply.ICFinancingBasicInfoService;
import com.sunxung.factoring.service.ledger.LedgerAccountBasicInfoService;
import com.sunxung.factoring.service.ledger.LedgerSupplierBankRefService;
import com.sunxung.factoring.service.project.IProjectCoreEnterpriseService;
import com.sunxung.factoring.service.supplier.ISupplierInfoService;
import com.sunxung.factoring.service.sys.*;
import com.sunxung.factoring.service.sys.dto.AttachmentDto;
import com.sunxung.factoring.service.tradingPlatform.PlatformService;
import com.sunxung.factoring.web.cashflowmanage.vo.LoanRecordToTradeVo;
import com.sunxung.factoring.web.cashflowmanage.vo.ReceivablesLoanRecordPlanFactoringRel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description : 现金流管理基础信息service实现类
 * @Author : JiaYf
 * @Date: 2021-11-02 18:15
 */
@Service
public class CashFlowManageBasicInfoServiceImpl extends ServiceImpl<CashFlowManageBaseInfoMapper, CashFlowManageBasicInfo>
        implements CashFlowManageBasicInfoService {

    @Value("${sop.url}")
    private String sopIp;

    @Autowired
    private CashFlowManageEntryInfoService cashFlowManageEntryInfoService;

    @Autowired
    private CashFlowManageBasicInfoService cashFlowManageBasicInfoService;
    @Autowired
    private CashFlowManageOutInfoService cashFlowManageOutInfoService;
    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;
    @Autowired
    private SerialNumberGenerator serialNumberGenerator;
    @Autowired
    private DictionaryService dictService;
    @Autowired
    private LedgerAccountBasicInfoService ledgerAccountBasicInfoService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${config.billingFactoringEntry.update.url}")
    private String billingFactoringEntryUpdateUrl;
    @Autowired
    private ICFinancingBasicInfoService financingBasicInfoService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private OrgService orgService;
    @Autowired
    private UserService userService;
    @Autowired
    private LedgerSupplierBankRefService ledgerSupplierBankRefService;
    @Autowired
    private SupplierBankCardInfoService supplierBankCardInfoService;
    @Autowired
    private IEnterpriseService enterpriseService;
    @Autowired
    private ISupplierInfoService supplierInfoService;
    @Autowired
    private IProjectCoreEnterpriseService projectCoreEnterpriseService;

    @Override
    public GridPage<CashFlowManageBaseVo> queryPage(SearchCashFlowManageVo searchCashFlowManageVo) {
        Long currentUserId = ThreadLocalUtil.getUserId();
        List<UserOrgRel> userOrgRelList = userService.findOrgRelByUserId(currentUserId);

        Boolean flag = true;
        List<Long> userIdList = new ArrayList<>();
        for (UserOrgRel userOrgRel : userOrgRelList) {
            Org org = orgService.get(userOrgRel.getOrgId());
            if (org != null && org.getDeptNo().equals(ConstantConversionUtil.dept_no)) {
                flag = true;
                break;
            } else {
                flag = false;
                if (userOrgRel.isUserIdentity()) {
                    // 如果是部门负责人，获取部门下所有人员Id
                    List<Long> userIds = userService.findUserIdByOrgId(userOrgRel.getOrgId());
                    userIdList.addAll(userIds);
                } else {
                    userIdList.add(currentUserId);
                }
            }
        }
        List<Long> pers = permissionService.getPermissionIdByUserId(ThreadLocalUtil.getUserId());
        Permission per = permissionService.getByEname(ConstantConversionUtil.VIEW_ALL_CASH_FLOW);
        if (per == null) {
            throw new ValidatorException(CodeUtil.FAIL, "数据可见-查看全员权限不能为空");
        }
        if (pers.contains(per.getId())
                || ThreadLocalUtil.getUser().getLoginName().equals(ConstantConversionUtil.ADMINISTORIES)) {
            flag = true;
        }

        if (!flag) {
            searchCashFlowManageVo.setUserIds(userIdList);
        }
        Page<CashFlowManageBaseVo> page = PageHelper.startPage(searchCashFlowManageVo.getPage(), searchCashFlowManageVo.getRows());
        List<CashFlowManageBaseVo> result = baseMapper.queryPage(searchCashFlowManageVo);
        if (CollectionUtil.isNotEmpty(result)) {
            for (CashFlowManageBaseVo cashFlowManageBaseVo : result) {
                if ("1".equals(cashFlowManageBaseVo.getEntryOutType())) {
                    //入账
                    CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowManageEntryInfoService.findByBaseInfo(cashFlowManageBaseVo.getId());
                    CashFlowManageBankVo bankVo = new CashFlowManageBankVo();

//                    String forObject = restTemplate.getForObject(
//                        sopIp + "/api/billingRecord/getById/"+cashFlowManageEntryInfo.getBankAccountId(), String.class);
//                    JSONObject jsonObject = JSONObject.parseObject(forObject);
                    Enterprise byId = enterpriseService.getById(
                            cashFlowManageEntryInfo.getCompanyId());
                    cashFlowManageBaseVo.setCompanyName(byId.getCorporateName());
                    bankVo.setBankName(cashFlowManageEntryInfo.getBankName());
                    bankVo.setBankAccount(cashFlowManageEntryInfo.getBankAccount());
                    //入账日期
                    bankVo.setGmtCreate(cashFlowManageBaseVo.getGmtCreate());
                    cashFlowManageBaseVo.setCashFlowManageBankVo(Arrays.asList(bankVo));


                } else if ("2".equals(cashFlowManageBaseVo.getEntryOutType())) {
                    //出账
                    List<CashFlowManageOutInfo> cashFlowManageOutInfoList = cashFlowManageOutInfoService.findByBaseInfoId(cashFlowManageBaseVo.getId());
                    if (CollectionUtil.isNotEmpty(cashFlowManageOutInfoList)) {
                        List<CashFlowManageBankVo> cashFlowManageBankVoList = cashFlowManageOutInfoList.stream().map(c -> {
                            CashFlowManageBankVo bankVo = new CashFlowManageBankVo(c);
                            return bankVo;
                        }).collect(Collectors.toList());
                        cashFlowManageBaseVo.setCashFlowManageBankVo(cashFlowManageBankVoList);
                    }
                }

            }
        }
        return new GridPage<>(searchCashFlowManageVo.getRows(), searchCashFlowManageVo.getPage(), page.getTotal(), result);
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public void add(CashFlowEntryInfoVo cashFlowEntryInfoVo, HttpServletRequest request) {
//        //保存 现金流管理基础信息
//        CashFlowManageBaseVo cashFlowManageBaseVo = cashFlowEntryInfoVo.getCashFlowManageBaseVo();
//        CashFlowManageBasicInfo cashFlowManageBasicInfo = new CashFlowManageBasicInfo(cashFlowManageBaseVo);
//        //状态 入账：1,已创建、2,已分配;出账：3,待处理、4,已完成
//        cashFlowManageBasicInfo.setCashStatus(1);
//        //出入账类型:1,入账;2,出账
//        cashFlowManageBasicInfo.setEntryOutType("1");
//        save(cashFlowManageBasicInfo);
//        //保存 现金流管理入账信息
//        CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowEntryInfoVo.getCashFlowManageEntryInfo();
//        cashFlowManageEntryInfo.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());
//        cashFlowManageEntryInfoService.save(cashFlowManageEntryInfo);
//        //保存 现金流管理入账信息附件
//        AttachmentDto attachmentDto = AttachmentDto.builder()
//                .setEntityId(cashFlowManageEntryInfo.getId())
//                .setChildEnum(FileModuleDict.ChildEnum.CASH_FLOW_ENTRY_FILE)
//                .build();
//        List<MultipartFile> fileList = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.CASH_FLOW_ENTRY_FILE_NAME);
//        sysAttachmentRefService.saveFileAndRef(fileList, attachmentDto);
//        // 开启分账
//        startLedgerProcess(cashFlowManageBasicInfo, cashFlowManageEntryInfo);
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(AddCashFlowRequest addCashFlowRequest) {
        if (addCashFlowRequest.getId() != null) {
            //更新操作
            CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowManageEntryInfoService.getById(
                    addCashFlowRequest.getId());
            BeanUtilsProxy.copyPropertiesNotIgnoreNull(addCashFlowRequest, cashFlowManageEntryInfo);
            cashFlowManageEntryInfoService.updateById(cashFlowManageEntryInfo);
            CashFlowManageBasicInfo cashFlowManageBasicInfo = this.getById(
                    cashFlowManageEntryInfo.getCashFlowManageBasicInfoId());
            if (addCashFlowRequest.getIncomeAmount() != null) {
                cashFlowManageBasicInfo.setAmount(addCashFlowRequest.getIncomeAmount());
            } else {
                cashFlowManageBasicInfo.setAmount(addCashFlowRequest.getInvoiceAmount());
            }
            cashFlowManageBasicInfo.setCashType(addCashFlowRequest.getType());
            this.updateById(cashFlowManageBasicInfo);
            updateLedgerInfo(cashFlowManageBasicInfo, cashFlowManageEntryInfo);
        } else {
            //新增操作
            CashFlowManageEntryInfo cashFlowManageEntryInfo = BeanUtilsProxy.copyProperties(
                    addCashFlowRequest, CashFlowManageEntryInfo.class);
            CashFlowManageBasicInfo cashFlowManageBasicInfo = new CashFlowManageBasicInfo();
            cashFlowManageBasicInfo.setCashStatus(1);
            //出入账类型:1,入账;2,出账
            cashFlowManageBasicInfo.setEntryOutType("1");
            cashFlowManageBasicInfo.setCashType(addCashFlowRequest.getType());
            if (addCashFlowRequest.getIncomeAmount() != null) {
                cashFlowManageBasicInfo.setAmount(addCashFlowRequest.getIncomeAmount());
            } else {
                cashFlowManageBasicInfo.setAmount(addCashFlowRequest.getInvoiceAmount());
            }
            save(cashFlowManageBasicInfo);
            cashFlowManageEntryInfo.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());
            cashFlowManageEntryInfoService.save(cashFlowManageEntryInfo);
            startLedgerProcess(cashFlowManageBasicInfo, cashFlowManageEntryInfo);
        }

    }

    /**
     * 修改分账信息
     *
     * @param cashFlowManageBasicInfo
     */
    private void updateLedgerInfo(CashFlowManageBasicInfo cashFlowManageBasicInfo, CashFlowManageEntryInfo cashFlowManageEntryInfo) {
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getOne(new QueryWrapper<LedgerAccountBasicInfo>()
                .eq("cash_flow_manage_basic_info_id", cashFlowManageBasicInfo.getId()));
        if (ledgerAccountBasicInfo != null) {
            String nowCashType = cashFlowManageBasicInfo.getCashType();
            String hisCashType = ledgerAccountBasicInfo.getLedgerType();

            LambdaUpdateWrapper<LedgerAccountBasicInfo> wrapper = new LambdaUpdateWrapper<>();
            if (nowCashType.equals(CashFlowEntryTypeDict.ChildEnum.BILLS_DISCOUNTED.getCode())) {
                //入账类型为票据贴现时,重新计算贴现费用
                if (cashFlowManageEntryInfo.getIncomeAmount() == null || cashFlowManageBasicInfo.getAmount() == null) {
                    throw new BusinessException(CodeUtil.FAIL, "票据金额或实际金额不能为空");
                }
                BigDecimal billAmount = cashFlowManageEntryInfo.getInvoiceAmount();
                BigDecimal amount = cashFlowManageEntryInfo.getRealAmount();
                if (billAmount.compareTo(amount) == -1) {
                    throw new BusinessException(CodeUtil.FAIL, "票据金额不能小于实际金额");
                }
                wrapper.set(LedgerAccountBasicInfo::getDiscountCharge, billAmount.subtract(amount));
                wrapper.set(LedgerAccountBasicInfo::getLedgerAmount, billAmount);
            } else {
                wrapper.set(LedgerAccountBasicInfo::getLedgerAmount, cashFlowManageBasicInfo.getAmount());
            }

            if (nowCashType.equals(CashFlowEntryTypeDict.ChildEnum.CASH.getCode())
                    && hisCashType.equals(CashFlowEntryTypeDict.ChildEnum.BILLS_DISCOUNTED.getCode())) {
                //如果入账类型由票据贴现->现金,需要将贴现费用置为空
                wrapper.set(LedgerAccountBasicInfo::getDiscountCharge, null);
            }
            wrapper.set(LedgerAccountBasicInfo::getLedgerType, cashFlowManageBasicInfo.getCashType());
            wrapper.set(LedgerAccountBasicInfo::getLedgerDate, cashFlowManageEntryInfo.getIncomeDate());
            //判断是下游回款还是上游回购
            if (cashFlowManageEntryInfo.getCompanyId() != null) {
                wrapper.set(LedgerAccountBasicInfo::getEnterpriseId, cashFlowManageEntryInfo.getCompanyId());
                SupplierInfo supplierInfo = supplierInfoService.getByEnterpriseId(cashFlowManageEntryInfo.getCompanyId());
                if (supplierInfo != null) {
                    //供应商为上游回购
                    wrapper.set(LedgerAccountBasicInfo::getLabel, 1);
                } else {
                    List<ProjectCoreEnterprise> projectCoreEnterpriseList = projectCoreEnterpriseService.getByEnterpriseId(cashFlowManageEntryInfo.getCompanyId());
                    if (CollectionUtil.isNotEmpty(projectCoreEnterpriseList)) {
                        //核心企业为上游回购
                        wrapper.set(LedgerAccountBasicInfo::getLabel, 0);
                    }
                }
            }
            wrapper.eq(LedgerAccountBasicInfo::getId, ledgerAccountBasicInfo.getId());
            ledgerAccountBasicInfoService.update(wrapper);
        }
    }

    /**
     * 新增分账信息
     *
     * @param cashFlowManageBasicInfo
     * @param cashFlowManageEntryInfo
     */
    private void startLedgerProcess(CashFlowManageBasicInfo cashFlowManageBasicInfo, CashFlowManageEntryInfo cashFlowManageEntryInfo) {

        String ledgerNumber = serialNumberGenerator.nextValue(ConstantUtil.LEDGER_CODE);

        LedgerAccountBasicInfo ledgerAccountBasicInfo = new LedgerAccountBasicInfo();
        ledgerAccountBasicInfo.setLedgerStatus(LedgerStatusDict.ChildEnum.PENDING.getCode());
        ledgerAccountBasicInfo.setLedgerType(cashFlowManageBasicInfo.getCashType());
//        ledgerAccountBasicInfo.setCurrency(cashFlowManageBasicInfo.getCurrency());

        String cashType = cashFlowManageBasicInfo.getCashType();
        if (cashType.equals(CashFlowEntryTypeDict.ChildEnum.BILLS_DISCOUNTED.getCode())) {
            //入账类型为票据贴现时

            //票据金额
            BigDecimal invoiceAmount = cashFlowManageEntryInfo.getInvoiceAmount();
            //实际金额
            BigDecimal realAmount = cashFlowManageEntryInfo.getRealAmount();

            if (invoiceAmount == null || realAmount == null) {
                throw new BusinessException(CodeUtil.FAIL, "票据金额或实际金额不能为空");
            }
            if (invoiceAmount.compareTo(realAmount) == -1) {
                throw new BusinessException(CodeUtil.FAIL, "票据金额不能小于实际金额");
            }
            ledgerAccountBasicInfo.setDiscountCharge(invoiceAmount.subtract(realAmount));
            ledgerAccountBasicInfo.setLedgerAmount(invoiceAmount);
        } else {
            ledgerAccountBasicInfo.setLedgerAmount(cashFlowManageBasicInfo.getAmount());
        }

        ledgerAccountBasicInfo.setLedgerNumber(ledgerNumber);
        ledgerAccountBasicInfo.setLedgerDate(cashFlowManageEntryInfo.getIncomeDate());
        //判断是下游回款还是上游回购
        if (cashFlowManageEntryInfo.getCompanyId() != null) {
            SupplierInfo supplierInfo = supplierInfoService.getByEnterpriseId(cashFlowManageEntryInfo.getCompanyId());
            if (supplierInfo != null) {
                //供应商为上游回购
                ledgerAccountBasicInfo.setLabel(1);
            } else {
                List<ProjectCoreEnterprise> projectCoreEnterpriseList = projectCoreEnterpriseService.getByEnterpriseId(cashFlowManageEntryInfo.getCompanyId());
                if (CollectionUtil.isNotEmpty(projectCoreEnterpriseList)) {
                    //核心企业为上游回购
                    ledgerAccountBasicInfo.setLabel(0);
                }
            }
        }
        ledgerAccountBasicInfo.setEnterpriseId(cashFlowManageEntryInfo.getCompanyId());
        ledgerAccountBasicInfo.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());
        ledgerAccountBasicInfoService.save(ledgerAccountBasicInfo);
    }

    @Override
    public CashFlowEntryInfoVo getEntryDetail(Long cashFlowManageBaseId) {

        CashFlowEntryInfoVo cashFlowEntryInfoVo = new CashFlowEntryInfoVo();

        //获取 现金流管理基础信息
        CashFlowManageBaseVo cashFlowManageBaseVo = baseMapper.getDetail(cashFlowManageBaseId);
        cashFlowEntryInfoVo.setCashFlowManageBaseVo(cashFlowManageBaseVo);

        //获取现金流入账信息
        CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowManageEntryInfoService.findByBaseInfo(cashFlowManageBaseId);
        if (cashFlowManageEntryInfo != null && cashFlowManageEntryInfo.getCompanyBelong() != null) {
            Dictionary dict = dictService.get(cashFlowManageEntryInfo.getCompanyBelong());
            if (dict != null) {
                cashFlowManageEntryInfo.setCompanyBelongName(dict.getName());
            }
            //查询企业名称 和 账户信息
//            String forObject = restTemplate.getForObject(
//                sopIp + "/api/billingRecord/getById/"+cashFlowManageEntryInfo.getBankAccountId(), String.class);
//            JSONObject jsonObject = JSONObject.parseObject(forObject);
            CashFlowManageBankVo bankVo = new CashFlowManageBankVo();

            Enterprise byId = enterpriseService.getById(
                    cashFlowManageEntryInfo.getCompanyId());
            cashFlowManageBaseVo.setCompanyName(byId.getCorporateName());

            bankVo.setBankName(cashFlowManageEntryInfo.getBankName());
            bankVo.setBankAccount(cashFlowManageEntryInfo.getBankAccount());
            bankVo.setGmtCreate(cashFlowManageEntryInfo.getGmtCreate());
            cashFlowManageBaseVo.setCashFlowManageBankVo(Lists.newArrayList(bankVo));
        }
        cashFlowEntryInfoVo.setCashFlowManageEntryInfo(cashFlowManageEntryInfo);

        //获取附件信息
        if (cashFlowManageEntryInfo != null && cashFlowManageEntryInfo.getId() != null) {
            AttachmentDto attachmentDto = AttachmentDto.builder()
                    .setEntityId(cashFlowManageEntryInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.CASH_FLOW_ENTRY_FILE)
                    .build();
            List<FileStorage> fileList = sysAttachmentRefService.getFiles(attachmentDto);
            cashFlowEntryInfoVo.setFileList(fileList);
        }

        //获取关联的分账信息
//        LedgerAccountManagement ledgerAccountManagement = ledgerAccountManagementService.findByCashFlowManageInfoId(cashFlowManageBaseVo.getId());
//        if (ledgerAccountManagement != null && ledgerAccountManagement.getId() != null) {
//            LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getByManageIdAndApproval(ledgerAccountManagement.getId());
//            if (ledgerAccountBasicInfo != null && ledgerAccountBasicInfo.getId() != null) {
//                RelationLedgerInfoVo relationLedgerInfoVo = new RelationLedgerInfoVo();
//                List<BillGoodsInfoVo> billGoodsInfoVos = settlementBasicInfoService.findRelationLedgerInfo(ledgerAccountBasicInfo.getId());
//                relationLedgerInfoVo.setBillGoodsInfoVoList(billGoodsInfoVos);
//
//                List<LedgerFundPossessionCost> fundPossessionCostList = ledgerFundPossessionCostService.findByBasicId(ledgerAccountBasicInfo.getId());
//                if (fundPossessionCostList != null && fundPossessionCostList.size() > 0) {
//                    BigDecimal possessionCost = fundPossessionCostList.stream().map(LedgerFundPossessionCost::getFundPossessionCost)
//                            .reduce(BigDecimal.ZERO, BigDecimal::add);
//                    relationLedgerInfoVo.setPossessionCost(possessionCost);
//                }
//
//                List<LedgerFundRetentionMoney> fundRetentionMoneyList = ledgerFundRetentionMoneyService.findByBasicId(ledgerAccountBasicInfo.getId());
//                if (fundRetentionMoneyList != null && fundRetentionMoneyList.size() > 0) {
//                    BigDecimal retentionMoney = fundRetentionMoneyList.stream().map(LedgerFundRetentionMoney::getAssignRetentionAmount)
//                            .reduce(BigDecimal.ZERO, BigDecimal::add);
//                    relationLedgerInfoVo.setRetentionMoney(retentionMoney);
//                }
//                cashFlowEntryInfoVo.setRelationLedgerInfoVo(relationLedgerInfoVo);
//            }
//        }

        return cashFlowEntryInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doUpdate(CashFlowEntryInfoVo cashFlowEntryInfoVo, HttpServletRequest request) {

        //更新 现金流管理基础信息
        CashFlowManageBaseVo cashFlowManageBaseVo = cashFlowEntryInfoVo.getCashFlowManageBaseVo();
        CashFlowManageBasicInfo cashFlowManageBaseInfo = new CashFlowManageBasicInfo(cashFlowManageBaseVo);
        cashFlowManageBaseInfo.setId(cashFlowManageBaseVo.getId());
        updateById(cashFlowManageBaseInfo);

        //更新 现金流管理入账信息
        CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowEntryInfoVo.getCashFlowManageEntryInfo();
        cashFlowManageEntryInfoService.updateById(cashFlowManageEntryInfo);

        //删除之前的附件
        if (cashFlowEntryInfoVo.getDeleteFileIdList() != null && cashFlowEntryInfoVo.getDeleteFileIdList().size() > 0) {
            sysAttachmentRefService.removeFilestorageAndRef(cashFlowEntryInfoVo.getDeleteFileIdList());
        }
        //保存新增的现金流管理入账信息附件
        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(cashFlowManageEntryInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.CASH_FLOW_ENTRY_FILE)
                .build();
        List<MultipartFile> fileList = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.CASH_FLOW_ENTRY_FILE_NAME);
        sysAttachmentRefService.saveFileAndRef(fileList, attachmentDto);

        //同步更新对应分账信息
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getOne(new QueryWrapper<LedgerAccountBasicInfo>()
                .eq("cash_flow_manage_basic_info_id", cashFlowManageBaseVo.getId()));
        if (ledgerAccountBasicInfo != null) {
//            Dictionary nowCashType = dictService.get(cashFlowManageBaseInfo.getCashType());
//            Dictionary hisCashType = dictService.get(ledgerAccountBasicInfo.getLedgerType());
            Dictionary nowCashType = null;
            Dictionary hisCashType = null;
            if (nowCashType == null) {
                throw new BusinessException(CodeUtil.FAIL, "现金流入账类型字典项不能为空");
            }

            LambdaUpdateWrapper<LedgerAccountBasicInfo> wrapper = new LambdaUpdateWrapper<>();
            if (nowCashType.getCode().equals(CashFlowEntryTypeDict.ChildEnum.BILLS_DISCOUNTED.getCode())) {
                //入账类型为票据贴现时,重新计算贴现费用
                if (cashFlowManageEntryInfo.getIncomeAmount() == null || cashFlowManageBaseInfo.getAmount() == null) {
                    throw new BusinessException(CodeUtil.FAIL, "票据金额或实际金额不能为空");
                }
                BigDecimal billAmount = cashFlowManageEntryInfo.getIncomeAmount();
                BigDecimal amount = cashFlowManageBaseInfo.getAmount();
                if (cashFlowManageEntryInfo.getIncomeAmount().compareTo(cashFlowManageBaseInfo.getAmount()) == -1) {
                    throw new BusinessException(CodeUtil.FAIL, "票据金额不能小于实际金额");
                }
                wrapper.set(LedgerAccountBasicInfo::getDiscountCharge, billAmount.subtract(amount));
                wrapper.set(LedgerAccountBasicInfo::getLedgerAmount, billAmount);
            } else {
                wrapper.set(LedgerAccountBasicInfo::getLedgerAmount, cashFlowManageBaseVo.getAmount());
            }

            if (nowCashType.getCode().equals(CashFlowEntryTypeDict.ChildEnum.CASH.getCode())
                    && hisCashType.getCode().equals(CashFlowEntryTypeDict.ChildEnum.BILLS_DISCOUNTED.getCode())) {
                //如果入账类型由票据贴现->现金,需要将贴现费用置为空
                wrapper.set(LedgerAccountBasicInfo::getDiscountCharge, null);
            }

            wrapper.set(LedgerAccountBasicInfo::getCurrency, cashFlowManageBaseVo.getCurrencyDict().getId());

            wrapper.set(LedgerAccountBasicInfo::getLedgerType, cashFlowManageBaseInfo.getCashType());
            wrapper.set(LedgerAccountBasicInfo::getLedgerDate, cashFlowManageBaseInfo.getCashDate());

            wrapper.eq(LedgerAccountBasicInfo::getId, ledgerAccountBasicInfo.getId());
            ledgerAccountBasicInfoService.update(wrapper);
        }
    }

    @Override
    public CashFlowDealOutInfoVo getDealOut(Long cashFlowManageBaseId) {
        CashFlowDealOutInfoVo cashFlowDealOutInfoVo = new CashFlowDealOutInfoVo();
        //获取 现金流管理基础信息
        CashFlowManageBaseVo cashFlowManageBaseVo = baseMapper.getDetail(cashFlowManageBaseId);
        cashFlowDealOutInfoVo.setCashFlowManageBaseVo(cashFlowManageBaseVo);

        //获取 现金流出账信息
        List<CashFlowManageOutInfo> cashFlowManageOutInfoList = cashFlowManageOutInfoService.findByBaseInfoId(cashFlowManageBaseVo.getId());
        if (cashFlowManageOutInfoList != null && cashFlowManageOutInfoList.size() > 0) {
            cashFlowManageOutInfoList.stream().forEach(c -> {
                //获取公司归属名称
                if (c.getFromCompanyBelong() != null) {
                    Dictionary dict = dictService.get(c.getFromCompanyBelong());
                    if (dict != null) {
                        c.setFromCompanyBelongName(dict.getName());
                    }
                }
                if (c.getToCompanyBelong() != null) {
                    Platform platform = platformService.getById(c.getToCompanyBelong());
                    if (platform != null) {
                        c.setToCompanyBelongName(platform.getPlatformName());
                    }
                }
            });
        }
        cashFlowDealOutInfoVo.setCashFlowManageOutInfoList(cashFlowManageOutInfoList);

        return cashFlowDealOutInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doDeal(CashFlowDealOutInfoVo cashFlowDealOutInfoVo) {
        CashFlowManageBaseVo baseInfo = cashFlowDealOutInfoVo.getCashFlowManageBaseVo();
        if (baseInfo == null || baseInfo.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "现金流基础信息不能为空");
        }
        //判断是否全部分完
        List<CashFlowManageOutInfo> outInfoList = cashFlowDealOutInfoVo.getCashFlowManageOutInfoList();
        //计算本次放款金额
        if (outInfoList == null || outInfoList.isEmpty()) {
            throw new BusinessException(CodeUtil.FAIL, "放款记录不能为空");
        }
        BigDecimal thisLoanAmountSum = outInfoList.stream().filter(o -> o.getLoanAmount() != null)
                .map(CashFlowManageOutInfo::getLoanAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (thisLoanAmountSum.compareTo(baseInfo.getAmount()) != 0) {
            throw new BusinessException(CodeUtil.FAIL, "放款金额总和必须等于总放款金额");
        }
        //修改状态为已完成
        updateStatus(baseInfo.getId(), "4");
        for (CashFlowManageOutInfo cashFlowManageOutInfo : outInfoList) {
            cashFlowManageOutInfo.setCashFlowManageBasicInfoId(baseInfo.getId());
            cashFlowManageOutInfoService.save(cashFlowManageOutInfo);
        }
        //如果处理的是融资本金或融资利息，需要向SOP更新账户信息
//        Dictionary principalDict = dictService.getByCode(CashFlowOutTypeDict.ChildEnum.FACTORING_PRINCIPAL.getCode());
//        Dictionary interestDict = dictService.getByCode(CashFlowOutTypeDict.ChildEnum.FACTORING_INTEREST.getCode());
//        if (principalDict == null || principalDict.getId() == null || interestDict == null || interestDict.getId() == null) {
//            throw new BusinessException(CodeUtil.FAIL, "现金流--款项类型字典项不能为空!");
//        }
//
//        CashFlowManageBasicInfo cashFlowManageBaseInfo = cashFlowManageBasicInfoService.getById(baseInfo.getId());
//        List<CashFlowManageOutInfo> cashFlowManageOutInfoList = cashFlowManageOutInfoService.findByBaseInfoId(baseInfo.getId());
//        if (baseInfo.getCashTypeDict().getId().equals(principalDict.getId()) || baseInfo.getCashTypeDict().getId().equals(interestDict.getId())) {
//            //向sop更新账户信息
//            updateCashFlowOutInfoToSop(cashFlowManageBaseInfo, cashFlowManageOutInfoList);
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncFromSop(LoanRecordToTradeVo loanRecordToTradeVo) {

        BillingFactoringBusinessLoanRecord loanRecord = loanRecordToTradeVo.getLoanRecord();
        BankAccountInfo bankAccountInfo = loanRecord.getBankAccountInfo();
        if (bankAccountInfo == null) {
            throw new BusinessException(CodeUtil.FAIL, "银行账号信息不能为空");
        }

        List<ReceivablesLoanRecordPlanFactoringRel> planFactoringRelList = loanRecordToTradeVo.getPlanFactoringRelList();
        if (planFactoringRelList != null && planFactoringRelList.size() > 0) {
            for (ReceivablesLoanRecordPlanFactoringRel planFactoringRel : planFactoringRelList) {
                Long accountsReceivableId = planFactoringRel.getAccountsReceivableId();
                if (accountsReceivableId == null) {
                    throw new BusinessException(CodeUtil.FAIL, "获取不到sop应收账款Id");
                }
                CFinancingBasicInfo financingBasicInfo = financingBasicInfoService
                        .getOne(new QueryWrapper<CFinancingBasicInfo>().eq("sop_accounts_receivable_id", accountsReceivableId));
                if (financingBasicInfo == null) {
                    throw new BusinessException(CodeUtil.FAIL, "获取不到对应的融资申请信息");
                }

                CashFlowManageBasicInfo cashFlowManageBasicInfo = cashFlowManageBasicInfoService.getOne(new QueryWrapper<CashFlowManageBasicInfo>()
                        .eq("business_number", financingBasicInfo.getBusinessNumber())
                        .eq("supplier_id", financingBasicInfo.getMainEnterpriseId())
                        .eq("entry_out_type", "2")
                        .eq("cash_type", CashFlowOutTypeDict.ChildEnum.LOAN_AMOUNT.getCode()));


                if (cashFlowManageBasicInfo == null) {
                    //新增
                    cashFlowManageBasicInfo = new CashFlowManageBasicInfo();
                    cashFlowManageBasicInfo.setSupplierId(financingBasicInfo.getMainEnterpriseId());
                    cashFlowManageBasicInfo.setEnterpriseCustomerInfoId(financingBasicInfo.getCoreEnterpriseId());
                    cashFlowManageBasicInfo.setTradingPlatformId(financingBasicInfo.getPlatformId());
                    cashFlowManageBasicInfo.setBusinessNumber(financingBasicInfo.getBusinessNumber());

                    cashFlowManageBasicInfo.setEntryOutType("2");
                    cashFlowManageBasicInfo.setCashType(CashFlowOutTypeDict.ChildEnum.LOAN_AMOUNT.getCode());
                    cashFlowManageBasicInfo.setContractNumber(financingBasicInfo.getContractNumber());
                    cashFlowManageBasicInfo.setRemark("sop同步数据");
                    cashFlowManageBasicInfo.setAmount(planFactoringRel.getReceivablesLoanAmount());
                    cashFlowManageBasicInfo.setCashStatus(4);
                    cashFlowManageBasicInfo.setCashDate(loanRecord.getThisLoanDate());

                    Dictionary currencyDict = dictService.getByCode(bankAccountInfo.getCurrency().getCode());
                    cashFlowManageBasicInfo.setCurrency(currencyDict.getId());
                    cashFlowManageBasicInfoService.save(cashFlowManageBasicInfo);
                } else {
                    //修改
                    BigDecimal amount = cashFlowManageBasicInfo.getAmount() == null ? BigDecimal.ZERO : cashFlowManageBasicInfo.getAmount();
                    cashFlowManageBasicInfo.setAmount(amount.add(planFactoringRel.getReceivablesLoanAmount()));
                    cashFlowManageBasicInfoService.updateById(cashFlowManageBasicInfo);
                }
                //同步出账数据
                CashFlowManageOutInfo cashFlowManageOutInfo = new CashFlowManageOutInfo();
                cashFlowManageOutInfo.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());

                if (bankAccountInfo.getCompanyOwnership() != null) {
                    Dictionary companyBelongDict = dictService.getByCode(bankAccountInfo.getCompanyOwnership().getCode());
                    cashFlowManageOutInfo.setFromCompanyBelong(companyBelongDict.getId());
                }

                cashFlowManageOutInfo.setLoanDate(loanRecord.getThisLoanDate());
                cashFlowManageOutInfo.setLoanAmount(planFactoringRel.getReceivablesLoanAmount());

                cashFlowManageOutInfo.setFromBankName(bankAccountInfo.getBankName());
                cashFlowManageOutInfo.setFromBankAccount(bankAccountInfo.getBankCardNo());
                if (loanRecord.getThisExecutor() != null && loanRecord.getThisExecutor().getId() != null) {
                    User user = userService.get(loanRecord.getThisExecutor().getId());
                    if (user != null && user.getName() != null) {
                        cashFlowManageOutInfo.setCurrExecutor(user.getName());
                    }
                }
                cashFlowManageOutInfoService.save(cashFlowManageOutInfo);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getOne(new QueryWrapper<LedgerAccountBasicInfo>()
                .eq("cash_flow_manage_basic_info_id", id));
        if (ledgerAccountBasicInfo != null) {
            if (ledgerAccountBasicInfo.getLedgerStatus() != null && LedgerStatusDict.ChildEnum.COMPLETE.getCode().equals(ledgerAccountBasicInfo.getLedgerStatus())) {
                throw new ValidatorException(CodeUtil.FAIL, "对应的分账数据状态为已完成，无法删除！");
            }

            //删除对应的分账数据
            ledgerAccountBasicInfoService.removeById(ledgerAccountBasicInfo.getId());
            //删除对应的现金流入账数据
            CashFlowManageEntryInfo cashFlowManageEntryInfo = cashFlowManageEntryInfoService.findByBaseInfo(id);
            if (cashFlowManageEntryInfo != null) {
                cashFlowManageEntryInfoService.removeById(cashFlowManageEntryInfo.getId());
            }
            //删除现金流基础信息数据
            cashFlowManageBasicInfoService.removeById(id);
        }
    }

    /**
     * 向sop更新账户信息
     *
     * @param cashFlowManageBasicInfo   现金流管理基础信息
     * @param cashFlowManageOutInfoList 关联的出账信息
     */
    private void updateCashFlowOutInfoToSop(CashFlowManageBasicInfo cashFlowManageBasicInfo, List<CashFlowManageOutInfo> cashFlowManageOutInfoList) {
        //组装数据
        BillingNonbusinessManageFactoringentry nobusinessManage = new BillingNonbusinessManageFactoringentry();


        if (cashFlowManageOutInfoList != null && cashFlowManageOutInfoList.size() > 0) {
            CashFlowManageOutInfo cashFlowManageOutInfo = cashFlowManageOutInfoList.get(0);
            nobusinessManage.setBillDate(cashFlowManageOutInfo.getLoanDate());

            String bankAccount = cashFlowManageOutInfo.getToBankAccount();
            BankAccountInfo bankAccountInfo = new BankAccountInfo();
            bankAccountInfo.setBankCardNo(bankAccount);
            nobusinessManage.setBankAccountInfo(bankAccountInfo);
        }

        Long billingFactoringEntryId = cashFlowManageBasicInfo.getBillingFactoringEntryId();
        if (billingFactoringEntryId == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应sop保理业务入账表Id");
        }
        nobusinessManage.setId(billingFactoringEntryId);


        ResponseEntity<String> responseEntity = restTemplate.postForEntity(billingFactoringEntryUpdateUrl, nobusinessManage, String.class);
        ResponseJson responseJson = JSONUtil.toBean(responseEntity.getBody(), ResponseJson.class);

        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value() || !responseJson.isSuccess()) {
            throw new BusinessException(CodeUtil.FAIL, "数据更新到sop失败：" + responseJson.getMsg().toString());
        }
    }

    public void updateStatus(Long id, String status) {
        UpdateWrapper<CashFlowManageBasicInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("cash_status", status);
        cashFlowManageBasicInfoService.update(updateWrapper);
    }
}
