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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.AccountPayment;
import com.fjhx.account.service.account.AccountPaymentService;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.flow.entity.flow.po.FlowExample;
import com.fjhx.flow.service.flow.FlowExampleService;
import com.fjhx.purchase.entity.invoice.po.InvoiceDetails;
import com.fjhx.purchase.entity.pay.dto.PayDto;
import com.fjhx.purchase.entity.pay.dto.PaySelectDto;
import com.fjhx.purchase.entity.pay.po.Pay;
import com.fjhx.purchase.entity.pay.po.PayDetail;
import com.fjhx.purchase.entity.pay.vo.PayDetailVo;
import com.fjhx.purchase.entity.pay.vo.PayVo;
import com.fjhx.purchase.mapper.pay.PayMapper;
import com.fjhx.purchase.service.invoice.InvoiceDetailsService;
import com.fjhx.purchase.service.pay.PayDetailService;
import com.fjhx.purchase.service.pay.PayService;
import com.fjhx.purchase.service.purchase.PurchaseService;
import com.fjhx.supply.entity.supplier.po.SupplierInfo;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.ruoyi.common.core.domain.BaseIdPo;
import com.ruoyi.common.exception.ServiceException;
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.CollectionUtils;
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.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 采购付款 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-13
 */
@Service
public class PayServiceImpl extends ServiceImpl<PayMapper, Pay> implements PayService {

    @Autowired
    private SupplierInfoService supplierInfoService;

    @Autowired
    private AccountPaymentService accountPaymentService;

    @Autowired
    private PayDetailService payDetailService;

    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private InvoiceDetailsService invoiceDetailsService;

    @Autowired
    private FlowExampleService flowExampleService;

    /**
     * 分页
     *
     * @param dto
     * @return
     */
    @Override
    public Page<PayVo> getPage(PaySelectDto dto) {
        IWrapper<Pay> wrapper = getWrapper();
        wrapper.orderByDesc("p", Pay::getCreateTime);

        // 供应商ID
        wrapper.eq("p", Pay::getSupplyId, dto.getSupplyId());

        // 付款方式
        wrapper.eq("p", Pay::getPayType, dto.getPayType());

        // 申请金额
        wrapper.ge("p", Pay::getAmount, dto.getStartAmount());
        wrapper.le("p", Pay::getAmount, dto.getEndAmount());

        // 申请时间
        wrapper.ge("p", Pay::getCreateTime, dto.getBeginTime());
        wrapper.le("p", Pay::getCreateTime, dto.getEndTime());

        if (StringUtils.isNotEmpty(dto.getStatus())) {
            wrapper.eq("p", Pay::getStatus, dto.getStatus());
        }
        //付款状态
        if (StringUtils.isNotEmpty(dto.getPayStatus())) {
            wrapper.eq("p", Pay::getPayStatus, dto.getPayStatus());
        }
        if (StringUtils.isNotEmpty(dto.getKeyword())) {
            wrapper.keyword(dto.getKeyword(), new SqlField(Pay::getUserName), new SqlField(Pay::getRemark));
        }
        Page<PayVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<PayVo> list = page.getRecords();

        if (list.size() == 0) {
            return page;
        }

        // 赋值供应商名称
        supplierInfoService.attributeAssign(list, Pay::getSupplyId, (item, supply) -> {
            item.setSupplyName(supply.getName());
        });


        List<Long> ids = list.stream().map(PayVo::getId).collect(Collectors.toList());

        // 查询付款状态
        List<AccountPayment> accountPaymentList = accountPaymentService.list(q -> q.in(AccountPayment::getBusinessId, ids));
        Map<Long, List<AccountPayment>> accountPaymentMap = accountPaymentList.stream().distinct()
                .collect(Collectors.groupingBy(AccountPayment::getBusinessId));

        // 查询流程id
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        Map<Long, Long> flowMap = flowExampleService.mapKV(FlowExample::getBusinessId, BaseIdPo::getId,
                q -> q.in(FlowExample::getBusinessId, ids));

        for (PayVo p : list) {

            // 赋值付款状态
            if (MapUtils.isNotEmpty(accountPaymentMap)) {
                List<AccountPayment> accountPayments = accountPaymentMap.getOrDefault(p.getId(), null);
                p.setPaymentStatus(accountPayments == null ? null : accountPayments.get(0).getStatus());
            }

            // 赋值流程id
            p.setFlowExampleId(flowMap.get(p.getId()));

        }

        return page;
    }

    @Override
    public PayVo detail(Long id) {
        Pay pay = this.getById(id);
        if (pay == null) {
            throw new ServiceException("没有找到采购付款记录");
        }

        PayVo result = BeanUtil.toBean(pay, PayVo.class);

        // 赋值供应商名称
        SupplierInfo supplierInfo = supplierInfoService.getById(pay.getSupplyId());
        result.setSupplyName(supplierInfo.getName());

        // 赋值采购付款明细
        List<PayDetail> payDetailList = payDetailService.list(q -> q.eq(PayDetail::getPayId, id));
        List<PayDetailVo> payDetailVoList = BeanUtil.copyToList(payDetailList, PayDetailVo.class);
        result.setPayDetailVoList(payDetailVoList);

        if (payDetailVoList.size() == 0) {
            return result;
        }

        // 赋值采购付款明细采购合同编号、采购合同金额
        purchaseService.attributeAssign(payDetailVoList, PayDetail::getPurchaseId, (item, purchase) -> {
            item.setPurchaseCode(purchase.getCode());
            item.setPurchaseAmount(purchase.getAmount());
        });

        // 赋值采购付款明细已收发票金额
        List<Long> purchaseIdList = payDetailVoList.stream()
                .map(PayDetail::getPurchaseId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (purchaseIdList.size() == 0) {
            return result;
        }

        //赋值已付款金额
        Map<Long, List<PayDetail>> payDetailMap = payDetailService.mapKGroup(PayDetail::getPurchaseId, q -> q.in(PayDetail::getPurchaseId, purchaseIdList));
        for (PayDetailVo payDetail : payDetailVoList) {
            List<PayDetail> payDetail1 = payDetailMap.get(payDetail.getPurchaseId());
            BigDecimal sumMoney = payDetail1.stream().map(PayDetail::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            payDetail.setSumMoney(sumMoney);
        }

        List<InvoiceDetails> list = invoiceDetailsService.list(q -> q.in(InvoiceDetails::getPurchaseId, purchaseIdList));
        Map<Long, BigDecimal> invoiceAmountMap = list.stream().collect(Collectors.toMap(
                InvoiceDetails::getPurchaseId,
                InvoiceDetails::getMoney,
                BigDecimal::add
        ));
        payDetailVoList.forEach(item -> item.setInvoiceAmount(invoiceAmountMap.getOrDefault(item.getPurchaseId(), BigDecimal.ZERO)));

        //赋值流程ID
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        FlowExample flowExample = flowExampleService.getOne(Wrappers.<FlowExample>query().lambda().eq(FlowExample::getBusinessId, id));
        // 赋值流程id
        if(ObjectUtil.isNotEmpty(flowExample)) {
            result.setFlowExampleId(flowExample.getId());
        }

        return result;
    }

    @Override
    public void add(PayDto payDto) {
        this.save(payDto);
    }

    @Override
    public void edit(PayDto payDto) {
        this.updateById(payDto);
    }

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


    /**
     * 采购付款统计
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> payStatistics(PaySelectDto dto) {
        List<Integer> statusList = Arrays.asList(0, 1, 2);// 付款状态  0未付款  1部分付款  2已付款'

        // 存放付款统计数据
        Map<String, Object> map = new HashMap<>();

        // 存放付款统计详情列表
        List<Map<String, Object>> list = new ArrayList<>();

        // 查询付款详情
        QueryWrapper<Pay> query = Wrappers.query();
        query.select("ifnull(pay_status,-1) payStatus,ifnull(amount,0) amount");
        query.groupBy("pay_status");
        List<Pay> pays = baseMapper.selectList(query);
        Map<String, List<Pay>> payMap = pays.stream().collect(Collectors.groupingBy(Pay::getPayStatus));

        // 计算合计金额
        BigDecimal amount = pays.stream().map(Pay::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        map.put("amount", amount);

        // 赋值每个付款状态的金额
        for (Integer status : statusList) {
            // 赋初始值
            Map<String, Object> statusMap = new HashMap<>();
            statusMap.put("payStatus", status);
            statusMap.put("payAmount", 0);
            // 赋值
            List<Pay> payList = payMap.get(status);
            if (CollectionUtils.isNotEmpty(payList)) {
                statusMap.put("payAmount", payList.get(0).getAmount());
            }
            list.add(statusMap);
        }
        map.put("payList", list);
        return map;
    }


}
