package com.zbkj.service.service.bcx;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.enums.BcxPerformanceReportBelongTypeEnum;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.bcx.BcxFapiaoSource;
import com.zbkj.common.model.bcx.BcxPlatformFee;
import com.zbkj.common.model.bcx.BcxSettle;
import com.zbkj.common.model.merchant.Merchant;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.order.OrderDetail;
import com.zbkj.common.model.product.Product;
import com.zbkj.common.model.user.User;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.bcx.BcxFapiaoSourceRequest;
import com.zbkj.common.response.bcx.BcxFapiaoSourceResponse;
import com.zbkj.common.response.bcx.BcxSummaryInfo;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.vo.DateLimitUtilVo;
import com.zbkj.service.dao.bcx.BcxFapiaoSourceDao;
import com.zbkj.service.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 发票源单据 服务实现类
 */
@Service
public class BcxFapiaoSourceServiceImpl extends ServiceImpl<BcxFapiaoSourceDao, BcxFapiaoSource> implements BcxFapiaoSourceService {

    @Resource
    private BcxFapiaoSourceDao dao;
    @Resource
    private UserService userService;
    @Resource
    private OrderService orderService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private BcxPlatformFeeService bcxPlatformFeeService;
    @Resource
    private MerchantService merchantService;
    @Resource
    private ProductService productService;

    @Override
    public PageInfo<BcxFapiaoSourceResponse> queryPagedList(BcxFapiaoSourceRequest request,
                                                            PageParamRequest pageParamRequest) {
        HashMap<String, Object> param = concatQueryParam(request);

        Page<BcxFapiaoSource> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<BcxFapiaoSourceResponse> sources = dao.selectSourceJoinApplyList(param);

        return CommonPage.copyPageInfo(page, CollUtil.isEmpty(sources) ? CollUtil.newArrayList() : sources);
    }

    private HashMap<String, Object> concatQueryParam(BcxFapiaoSourceRequest request) {
        Integer userId = userService.getUserIdException();
        HashMap<String, Object> param = new HashMap<>();
        param.put("sourceNo", request.getSourceNo());
        param.put("applyNo", request.getApplyNo());
        param.put("fapiaoNo", request.getFapiaoNo());
        if (StrUtil.isNotEmpty(request.getSourceTime())) {
            DateLimitUtilVo sourceTime = CrmebDateUtil.getDateLimit(request.getSourceTime());
            param.put("sourceTimeStart", sourceTime.getStartTime());
            param.put("sourceTimeEnd", sourceTime.getEndTime());
        }
        if (StrUtil.isNotEmpty(request.getFapiaoTime())) {
            DateLimitUtilVo fapiaoTime = CrmebDateUtil.getDateLimit(request.getSourceTime());
            param.put("fapiaoTimeStart", fapiaoTime.getStartTime());
            param.put("fapiaoTimeEnd", fapiaoTime.getEndTime());
        }
        param.put("fapiaoStatus", request.getFapiaoStatus());
        param.put("sourceType", request.getSourceType());
        param.put("categoryId", request.getCategoryId());
        param.put("writer", request.getWriter());
        param.put("productInfo", request.getProductInfo());
        param.put("receiverId", userId);
        return param;
    }

    @Override
    public List<BcxFapiaoSource> queryByApplyNo(String applyNo) {
        LambdaQueryWrapper<BcxFapiaoSource> lqw = Wrappers.lambdaQuery();
        lqw.in(BcxFapiaoSource::getApplyNo, applyNo);
        return dao.selectList(lqw);
    }

    @Override
    public BcxSummaryInfo getSummaryInfo(BcxFapiaoSourceRequest request) {
        Map<String, Object> queryParam = concatQueryParam(request);
        return dao.querySummary(queryParam);
    }

    @Override
    public void saveSourceFromOrder(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(orderNo);
        BcxPlatformFee bcxPlatformFee = bcxPlatformFeeService.queryByOrderNo(orderNo, 0);
        User receiver = userService.getById(order.getUid());
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        User merchantUser = userService.getByAccount("org_" + merchant.getIdentityNo());
        Integer productId = orderDetails.stream().map(OrderDetail::getProductId).distinct().findFirst().orElse(0);
        Product product = productService.getById(productId);

        //订单发票源
        BcxFapiaoSource source = new BcxFapiaoSource();
        source.setSourceNo(orderNo);
        source.setSourceType(0);//订单
        source.setSourceTime(order.getPayTime());
        if (merchantUser != null) {
            source.setWriter(merchantUser.getRealName());
            source.setWriterId(merchantUser.getId());
        }
        source.setProductInfo(orderDetails.stream().map(OrderDetail::getProductName).collect(Collectors.joining(",")));
        source.setReceiver(StrUtil.isNotBlank(receiver.getRealName()) ? receiver.getRealName() : "小程序用户:" + receiver.getPhone());
        source.setReceiverId(receiver.getId());
        source.setCategoryId(product.getCategoryId());
        source.setAmount(order.getPayPrice());
        source.setQuantity(orderDetails.stream().map(OrderDetail::getPayNum).reduce(0, Integer::sum));
        source.setPrice(orderDetails.stream().map(OrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::max));
        dao.insert(source);

        //平台服务费发票源
        User platform = userService.getPlatformUser();
        BcxFapiaoSource platformFeeSource = new BcxFapiaoSource();
        platformFeeSource.setSourceNo(orderNo);
        platformFeeSource.setSourceType(1);//平台费
        platformFeeSource.setSourceTime(order.getPayTime());
        if (platform != null) {
            platformFeeSource.setWriter(platform.getRealName());
            platformFeeSource.setWriterId(platform.getId());
        }
        platformFeeSource.setProductInfo(orderDetails.stream().map(OrderDetail::getProductName).collect(Collectors.joining(",")));
        if (merchantUser != null) {
            platformFeeSource.setReceiver(merchantUser.getRealName());
            platformFeeSource.setReceiverId(merchantUser.getId());
        }
        platformFeeSource.setCategoryId(product.getCategoryId());
        platformFeeSource.setAmount(bcxPlatformFee.getPlatFee());
        platformFeeSource.setQuantity(null);
        platformFeeSource.setPrice(bcxPlatformFee.getPlatFee());
        dao.insert(platformFeeSource);
    }

    @Override
    public Map<Integer, BcxFapiaoSource> getMapBySourceIdList(List<Integer> sourceIds) {
        LambdaQueryWrapper<BcxFapiaoSource> lqw = Wrappers.lambdaQuery();
        lqw.in(BcxFapiaoSource::getId, sourceIds);
        List<BcxFapiaoSource> sourceList = dao.selectList(lqw);
        if (CollUtil.isEmpty(sourceList)) {
            return CollUtil.newHashMap(0);
        }
        return sourceList.stream().distinct().collect(Collectors.toMap(BcxFapiaoSource::getId, Function.identity(), (o, n) -> o));
    }

    /**
     * description：分销结算，生成开票源
     * author：linchunpeng
     * date：2024/4/12
     */
    @Override
    public void saveSourceFromBrokerage(BcxSettle bcxSettle) {
        //0-商品购买 1-平台服务费2-渠道服务费 3-分销服务费
        int sourceType = -100;//-100表示不生成发票源
        if (bcxSettle.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.CHANNEL.getValue().intValue()) {
            //渠道结算
            sourceType = 2;
        } else if (bcxSettle.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()) {
            //分销商结算
            sourceType = 3;
        }
        //-100表示不生成发票源，不等于-100，才需要生成发票源
        if (sourceType != -100) {
            //申请方
            User applyUser = userService.getPlatformUser();
            //开票方
            User openUser = userService.getById(bcxSettle.getBelongId());

            BcxFapiaoSource source = new BcxFapiaoSource();
            source.setSourceNo(bcxSettle.getSettleNo());
            source.setSourceType(sourceType);
            source.setSourceTime(bcxSettle.getCreateTime());
            source.setWriter(openUser.getRealName());
            source.setWriterId(openUser.getId());
            source.setReceiver(applyUser.getRealName());
            source.setReceiverId(applyUser.getId());
            source.setAmount(bcxSettle.getBrokerageTotalPrice());
            dao.insert(source);
        }
    }

    /**
     * description：分销撤销结算，删除未申请开票的开票源
     * author：linchunpeng
     * date：2024/4/12
     */
    @Override
    public void deleteSourceFromBrokerage(String settleNo) {
        //根据结算单号，查询开票源
        LambdaQueryChainWrapper<BcxFapiaoSource> lqw = this.lambdaQuery();
        lqw.eq(BcxFapiaoSource::getSourceNo, settleNo);
        lqw.last("limit 1");
        List<BcxFapiaoSource> list = lqw.list();
        if (CollectionUtil.isNotEmpty(list)) {
            BcxFapiaoSource source = list.get(0);
            if (StringUtils.isNotBlank(source.getApplyNo())) {
                throw new CrmebException(CommonResultCode.ERROR.setMessage("已申请开票的结算单不能撤销"));
            }
            //撤销结算，需要删除开票记录
            this.removeById(source.getId());
        }
    }

}
