package com.njzscloud.dispose.wh.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.sn.support.SnUtil;
import com.njzscloud.dispose.cst.order.mapper.OrderPaymentRecordMapper;
import com.njzscloud.dispose.cst.order.mapper.OrderTransMapper;
import com.njzscloud.dispose.cst.order.pojo.entity.OrderPaymentRecordEntity;
import com.njzscloud.dispose.cst.order.pojo.result.OrderTransResult;
import com.njzscloud.dispose.wh.constant.SalesOrderStatus;
import com.njzscloud.dispose.wh.mapper.SalesOrderMapper;
import com.njzscloud.dispose.wh.pojo.entity.SalesOrderEntity;
import com.njzscloud.dispose.wh.pojo.param.AddSalesOrderParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;

/**
 * 销售单
 *
 * @author ljw
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SalesOrderService extends ServiceImpl<SalesOrderMapper, SalesOrderEntity> {

    private final OrderTransMapper orderTransMapper;
    private final OrderPaymentRecordMapper orderPaymentRecordMapper;

    /**
     * 新增
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(AddSalesOrderParam param) {
        SalesOrderEntity entity = BeanUtil.copyProperties(param, SalesOrderEntity.class);
        entity.setSn(this.generateSn());
        entity.setSalesOrderStatus(SalesOrderStatus.JinXingZhong);
        this.save(entity);
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(Long transOrderId) {
        OrderTransResult orderTrans = orderTransMapper.getById(transOrderId);
        // 通过transOrderId查询付费记录表，计算settle_money的总和
        BigDecimal totalMoney = orderPaymentRecordMapper.selectList(
                Wrappers.<OrderPaymentRecordEntity>lambdaQuery()
                    .eq(OrderPaymentRecordEntity::getTransId, transOrderId)
            ).stream()
            .map(OrderPaymentRecordEntity::getSettleMoney)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        this.add(BeanUtil.copyProperties(orderTrans, AddSalesOrderParam.class)
            .setOrderTransId(transOrderId)
            .setSn(this.generateSn())
            .setSalesOrderStatus(SalesOrderStatus.YiFaHuo)
            .setOrderDate(orderTrans.getOrderTime().toLocalDate())
            .setShipmentDate(LocalDate.now())
            .setQuantity(orderTrans.getEstimatedQuantity())
            .setTotalMoney(totalMoney)
            .setMemo("销售预约单自动添加"));
    }

    /**
     * 修改
     */
    public void modify(SalesOrderEntity salesOrderEntity) {
        this.updateById(salesOrderEntity);
    }

    /**
     * 删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        this.removeBatchByIds(ids);
    }

    /**
     * 详情
     */
    public SalesOrderEntity detail(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     */
    public PageResult<SalesOrderEntity> paging(PageParam pageParam, SalesOrderEntity entity) {
        return PageResult.of(this.page(pageParam.toPage(), Wrappers.query(entity)
            .eq("deleted", Boolean.FALSE)
            .like(StrUtil.isNotBlank(entity.getSn()), "sn", entity.getSn())
            .eq(entity.getSalesOrderStatus() != null, "purchase_order_status", entity.getSalesOrderStatus())));
    }

    /**
     * 生成订单号
     *
     * @return sn 订单号
     */
    public String generateSn() {
        String sn = SnUtil.next("Sales-SN");
        if (this.exists(Wrappers.<SalesOrderEntity>lambdaQuery().eq(SalesOrderEntity::getSn, sn)
            .eq(SalesOrderEntity::getDeleted, Boolean.FALSE))) {
            this.generateSn();
        }
        return sn;
    }

}
