package com.fjhx.purchase.service.refund.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.account.entity.account.po.AccountRunningWater;
import com.fjhx.account.service.account.AccountPaymentService;
import com.fjhx.account.service.account.AccountRunningWaterService;
import com.fjhx.purchase.entity.refund.dto.RefundDto;
import com.fjhx.purchase.entity.refund.dto.RefundSelectDto;
import com.fjhx.purchase.entity.refund.enums.RefundEnum;
import com.fjhx.purchase.entity.refund.po.Refund;
import com.fjhx.purchase.entity.refund.vo.RefundVo;
import com.fjhx.purchase.mapper.refund.RefundMapper;
import com.fjhx.purchase.service.refund.RefundService;
import com.fjhx.supply.entity.supplier.po.SupplierInfo;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.common.utils.wrapper.SqlField;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 退款管理 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-13
 */
@Service
public class RefundServiceImpl extends ServiceImpl<RefundMapper, Refund> implements RefundService {

    @Autowired
    private SupplierInfoService supplierInfoService;

    @Autowired
    private AccountPaymentService accountPaymentService;

    @Autowired
    private AccountRunningWaterService accountRunningWaterService;

    @Override
    public Page<RefundVo> getPage(RefundSelectDto dto) {
        IWrapper<Refund> wrapper = getWrapper();
        wrapper.orderByDesc("r", Refund::getCreateTime);
        if(StringUtils.isNotEmpty(dto.getStatus())){
            wrapper.eq("r", Refund::getStatus, dto.getStatus());
        }
        if(StringUtils.isNotEmpty(dto.getRefundStatus())){
            wrapper.eq("r", Refund::getRefundStatus, dto.getRefundStatus());
        }
        if(StringUtils.isNotEmpty(dto.getKeyword())){
            wrapper.keyword(dto.getKeyword(),new SqlField(Refund::getRefundName));
        }
        Page<RefundVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<RefundVo> list = page.getRecords();
        if(CollectionUtils.isNotEmpty(list)) {
            //查询供应商
            List<Long> supplyIds = list.stream().map(RefundVo::getSupplyId).collect(Collectors.toList());
            List<SupplierInfo> supplierInfoList = supplierInfoService.list(Wrappers.<SupplierInfo>query().lambda().in(SupplierInfo::getId, supplyIds));
            Map<Long, List<SupplierInfo>> supplyMap = supplierInfoList.stream().distinct().collect(Collectors.groupingBy(SupplierInfo::getId));
            //查询应退款金额
            List<Long> ids = list.stream().map(RefundVo::getId).collect(Collectors.toList());
//            List<AccountPayment> accountPaymentList = accountPaymentService.list(Wrappers.<AccountPayment>query().lambda().in(AccountPayment::getBusinessId,ids)
//                    .eq(AccountPayment::getStatus, PaymentStatusEnum.REJECT.getKey()));
//            Map<Long,List<AccountPayment>> accMap = accountPaymentList.stream().collect(Collectors.groupingBy(AccountPayment::getBusinessId));
            List<AccountRunningWater> accountRunningWaters = accountRunningWaterService.list(Wrappers.<AccountRunningWater>query().lambda().in(AccountRunningWater::getBusinessId, ids));
            Map<Long, List<AccountRunningWater>> arwMap = accountRunningWaters.stream().collect(Collectors.groupingBy(AccountRunningWater::getBusinessId));
            for (RefundVo p : list) {
                if (MapUtils.isNotEmpty(supplyMap)) {//赋值供应商
                    List<SupplierInfo> supplys = supplyMap.getOrDefault(p.getSupplyId(), null);
                    p.setSupplyName(supplys == null ? null : supplys.get(0).getName());
                }
//                if(MapUtils.isNotEmpty(accMap)){//赋值已退款总金额
//                    List<AccountPayment> sumList = accMap.getOrDefault(p.getId(),null);
//                    BigDecimal sum = sumList.stream().map(AccountPayment::getAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
//                    p.setSumRefundMoney(sum==null?BigDecimal.ZERO:sum);
//                }
                if (MapUtils.isNotEmpty(arwMap)) {//赋值已退款总金额
                    p.setSumRefundMoney(BigDecimal.ZERO);
                    List<AccountRunningWater> sumList = arwMap.getOrDefault(p.getId(), null);
                    if (ObjectUtils.isNotEmpty(sumList)) {
                        BigDecimal sum = sumList.stream().map(AccountRunningWater::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        p.setSumRefundMoney(sum);
                    }
                }
            }
        }
        return page;
    }

    @Override
    public RefundVo detail(Long id) {
        Refund Refund = this.getById(id);
        RefundVo result = BeanUtil.toBean(Refund, RefundVo.class);
        return result;
    }

    @Override
    public void add(RefundDto refundDto) {
        this.save(refundDto);
    }

    @Override
    public void edit(RefundDto refundDto) {
        this.updateById(refundDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 到款登记
     * @param refundDto
     */
    @Override
    @DSTransactional
    public void receiptRegistration(RefundDto refundDto) {
        if(ObjectUtils.isEmpty(refundDto.getId())||
                ObjectUtils.isEmpty(refundDto.getReceiptAmount())||
                ObjectUtils.isEmpty(refundDto.getReceiptAccountManagementId())){
            throw new ServiceException("参数异常");
        }
        Refund refund = this.getById(refundDto.getId());
        if(ObjectUtils.isEmpty(refund)){
            throw new ServiceException("退货单不存在");
        }
        //判断当前所收的金额修改退款状态
        BigDecimal newAmount = refundDto.getReceiptAmount();
        List<AccountRunningWater> accountRunningWaters = accountRunningWaterService.list(Wrappers.<AccountRunningWater>query().lambda().select(AccountRunningWater::getAmount).eq(AccountRunningWater::getBusinessId,refund.getId()));
        BigDecimal sumAmount = accountRunningWaters.stream().map(AccountRunningWater::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (ObjectUtils.isNotEmpty(sumAmount)) {
            if ((sumAmount.add(newAmount)).compareTo(refund.getAmount()) > -1) {//已退款
                refund.setRefundStatus(RefundEnum.RE_20.getKey());
            } else {//部分退款
                refund.setRefundStatus(RefundEnum.RE_10.getKey());
            }
        }
        this.updateById(refund);
        //添加一条资金流水
        AccountRunningWater accountRunningWater = new AccountRunningWater();

        accountRunningWater.setCompanyId(SecurityUtils.getCompanyId());

        accountRunningWater.setAccountManagementId(refundDto.getReceiptAccountManagementId());
        accountRunningWater.setStatus("10");// 收入
        accountRunningWater.setBusinessId(refund.getId());
        accountRunningWater.setAmount(refundDto.getReceiptAmount());
        accountRunningWater.setCurrency(refund.getCurrency());
        accountRunningWater.setReceived("20");// 合同到账（10:是，20:否）
        accountRunningWater.setName(refundDto.getReceiptName());
        accountRunningWater.setOpeningBank(refundDto.getReceiptOpeningBank());
        accountRunningWater.setAccountOpening(refundDto.getReceiptAccountOpening());
        accountRunningWater.setType("20"); // 添加流水类型 10 打款  20 到款登记
        accountRunningWater.setTransactionTime(new Date());
        accountRunningWaterService.save(accountRunningWater);
    }

}
