package com.gree.mall.manager.logic.order;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.PayDetail;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.listvo.OrderInfoVO;
import com.gree.mall.manager.bean.order.OrderInfoAddBean;
import com.gree.mall.manager.bean.order.OrderInfoDetailBean;
import com.gree.mall.manager.bean.order.OrderOldProductAdd;
import com.gree.mall.manager.bean.order.OrderOldProductDTO;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.enums.ExamineStatusEnum;
import com.gree.mall.manager.enums.IsYesNoEnum;
import com.gree.mall.manager.enums.OrderStatusEnum;
import com.gree.mall.manager.enums.material.GoodsMaterialTypeEnum;
import com.gree.mall.manager.enums.material.PayTypeEnum;
import com.gree.mall.manager.enums.material.StateEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.common.WechatLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.StringUtil;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 线下销售订单
 * @author ：lijh
 * @description：TODO
 * @date ：2024/2/2 16:31
 */
@Service
@RequiredArgsConstructor
public class OrderOfflineLogic {

    private final CommonLogic commonLogic;
    private final WechatLogic wechatLogic;
    private final CommonMapper commonMapper;
    private final OrderInfoService orderInfoService;
    private final OrderDetailService orderDetailService;
    private final GoodsMaterialService goodsMaterialService;
    private final GoodsMaterialItemService goodsMaterialItemService;
    private final GoodsCategoryService goodsCategoryService;
    private final GoodsService goodsService;
    private final GoodsSpecService goodsSpecService;
    private final GoodsCategoryItemService goodsCategoryItemService;
    private final OrderOldProductService orderOldProductService;
    private final OrderOldProductItemService orderOldProductItemService;
    private final GoodsMaterialStorageService goodsMaterialStorageService;
    /**
     * 线下销售单列表
     * @param zfireParamBean
     * @return
     */
    public IPage<OrderInfoVO> list(ZfireParamBean zfireParamBean){
        AdminUserCom adminUser = commonLogic.getAdminUser();
        zfireParamBean = FieldUtils.supplyParam(zfireParamBean,OrderInfoVO.class,adminUser);
        IPage<OrderInfoVO> orderInfoVOIPage = commonMapper.queryOrderInfoList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
        return orderInfoVOIPage;
    }

    /**
     * 添加/编辑线下单
     * @param orderInfoAddBean
     */
    @Transactional
    public String addOfflineOrder(OrderInfoAddBean orderInfoAddBean){
        AdminUserCom adminUser = commonLogic.getAdminUser();

        OrderInfo orderInfo = null;
        if(StringUtils.isNotBlank(orderInfoAddBean.getOrderId())){
            orderInfo = orderInfoService.getById(orderInfoAddBean.getOrderId());
            if(orderInfo == null){
                throw new RemoteServiceException("订单不存在");
            }
            if(!orderInfo.getOrderStatus().equals(OrderStatusEnum.NOPAY.toString())){
                throw new RemoteServiceException("已支付订单不可编辑");
            }
            if(orderInfo.getOrderStatus().equals(OrderStatusEnum.TIMEOUT.toString())){
                throw new RemoteServiceException("订单已超时取消，请重新下单");
            }
        }
        if(orderInfo == null){
            orderInfo = new OrderInfo();
        }
        BeanUtil.copyProperties(orderInfoAddBean,orderInfo,"orderId");
        if(StringUtils.isBlank(orderInfo.getOrderId())){
            orderInfo.setOrderId("N"+IdWorker.getIdStr());
        }
        orderInfo.setCompanyWechatId(adminUser.getCompanyWechatId());
        orderInfo.setCompanyName(adminUser.getCompanyName());
        orderInfo.setIsOld(orderInfoAddBean.getIsOld());

        Integer totalNum = 0;
        BigDecimal totalPrice = BigDecimal.ZERO;
        String orderTitle = "";
        List<OrderDetail> orderDetails = orderInfoAddBean.getOrderDetails();
        if(CollectionUtils.isEmpty(orderDetails)){
            throw new RemoteServiceException("请选择商品信息");
        }
        for(OrderDetail orderDetail : orderDetails){


            if(orderDetail.getPrice() == null){
                throw new RemoteServiceException("单价不能为空");
            }
            if(orderDetail.getNum() == null){
                throw new RemoteServiceException("购买数量不能为空");
            }
            if(orderDetail.getNum() <= 0){
                throw new RemoteServiceException("购买数量必须大于0");
            }

            if(orderDetail.getNum() == 0 && orderInfoAddBean.getIsOld().equals(IsYesNoEnum.YES.getKey())){
                throw new RemoteServiceException("以旧换新，购买数量必须等于0");
            }

            //物料
            if(orderDetail.getFlag() == 2) {
                if(StringUtils.isBlank(orderDetail.getGoodsMaterialId())){
                    throw new RemoteServiceException("请选择规格型号");
                }
                GoodsMaterial gm = goodsMaterialService.getById(orderDetail.getGoodsMaterialId());
                if (gm == null) {
                    throw new RemoteServiceException("物料id有误，请检查");
                }
                orderDetail = supplyOrderDetail(orderInfo.getOrderId(),gm,orderDetail);
                orderTitle += gm.getGoodsName() + ",";

            }else{
                //商品规格
                Boolean isGm = false;
                GoodsSpec goodsSpec = goodsSpecService.getById(orderDetail.getGoodsSpecId());

                if(StringUtils.isNotBlank(goodsSpec.getGoodsCode())){
                    GoodsMaterial gm = goodsMaterialService.getById(orderDetail.getGoodsMaterialId());
                    if(gm != null) {
                        orderDetail = supplyOrderDetail(orderInfo.getOrderId(), gm, orderDetail);
                        isGm = true;
                    }
                }
                if(!isGm){
                    Goods goods = goodsService.getById(goodsSpec.getGoodsId());
                    orderDetail.setOrderId(orderInfo.getOrderId());
                    orderDetail.setBrandId(goods.getBrandId());
                    orderDetail.setBrandName(goods.getBrandName());
                    orderDetail.setMainNumber(goodsSpec.getMainId());
                    orderDetail.setMainName(goodsSpec.getMainName());
                    orderDetail.setSmallNumber(goodsSpec.getSmallId());
                    orderDetail.setSmallName(goodsSpec.getSmallName());
                    orderDetail.setGoodsName(goods.getGoodsName());
                    orderDetail.setGoodsSpecName(goodsSpec.getSpecValue());
                    orderDetail.setImgUrl(goodsSpec.getImgUrl());
                    orderDetail.setInsideNum(1);
                    orderDetail.setOutNum(1);
                    orderDetail.setPartNum(0);
                    orderDetail.setIsVr(goods.getIsVr());
                }

            }
            orderDetail.setTotalPrice(orderDetail.getPrice().multiply(BigDecimal.valueOf(orderDetail.getNum())));
            orderDetail.setPayAmount(orderDetail.getTotalPrice());
            orderDetail.setNeedPayAmount(orderDetail.getPayAmount());
            orderDetail.setProfitAmount(orderDetail.getPayAmount());
            orderDetail.setOrderSmallType(orderInfoAddBean.getOrderSmallType());
            orderDetail.setOrderSmallTypeText(orderInfoAddBean.getOrderSmallTypeText());
            totalNum += orderDetail.getNum();
            totalPrice = orderDetail.getTotalPrice().add(totalPrice);
        }
        orderInfo.setOrderStatus(OrderStatusEnum.NOPAY.toString());
        orderInfo.setTotalNum(totalNum);
        orderInfo.setTotalAmount(totalPrice);
        orderInfo.setTotalProductAmount(totalPrice);
        orderInfo.setPayAmount(totalPrice);
        orderInfo.setCompanyWechatId(adminUser.getCompanyWechatId());
        orderInfo.setCompanyWechatName(adminUser.getCompanyName());
        orderInfo.setPayTypeId(orderInfoAddBean.getPayType().getKey());
        orderInfo.setPayType(orderInfoAddBean.getPayType().getRemark());
        orderInfo.setIsOld(orderInfoAddBean.getIsOld());
        orderInfo.setSaleType(2);
        orderInfo.setPhone(orderInfo.getRecePhone());
        orderInfo.setUserName(orderInfo.getReceUserName());
        if (StringUtils.isNotBlank(orderTitle)) {
            orderInfo.setOrderTitle(orderTitle.substring(0,orderTitle.length() - 1));
        }
        orderInfo.setSource("PC");



        //旧机回收

        if (!CollectionUtils.isEmpty(orderInfoAddBean.getOrderOldProductAdds())) {

            List<OrderOldProduct> orderOldProducts = new ArrayList<>();
            List<OrderOldProductItem> orderOldProductItems = new ArrayList<>();

            for (OrderOldProductAdd orderOldProductDTO : orderInfoAddBean.getOrderOldProductAdds()) {

                GoodsCategoryItem goodsCategoryItemDto = goodsCategoryItemService.getById(orderOldProductDTO.getId());
                OrderOldProduct orderOldProduct = new OrderOldProduct();
                this.productCategory(orderOldProduct, goodsCategoryItemDto);
                orderOldProduct.setSaleType(orderInfo.getSaleType());
                orderOldProduct.setOrderId(orderInfo.getOrderId());
                orderOldProduct.setId(IdWorker.getIdStr());
                orderOldProduct.setPayAmount(orderOldProductDTO.getPayAmount());
                orderOldProduct.setNum(orderOldProductDTO.getNum());
                orderOldProduct.setYjhxDkFlag(adminUser.getAdminCompanyWechat().getYjhxDkFlag());

                orderOldProduct.setPrice(goodsCategoryItemDto.getPrice());

                for (String goodsCategoryItem : orderOldProductDTO.getItemIds()) {

                    GoodsCategoryItem goodsCategoryItems = goodsCategoryItemService.getById(goodsCategoryItem);
                    OrderOldProductItem orderOldProductItem = this.productCategoryItem(goodsCategoryItems);
                    orderOldProductItem.setOrderId(orderOldProduct.getOrderId());
                    orderOldProductItem.setOrderOldProductId(orderOldProduct.getId());

                    orderOldProductItems.add(orderOldProductItem);

                }

                if (adminUser.getAdminCompanyWechat().getYjhxDkFlag().equals(1))
                    orderInfo.setPayAmount(orderInfo.getPayAmount().subtract(orderOldProduct.getPayAmount()));

                for (OrderDetail orderDetail : orderDetails) {
                    orderDetail.setTotalPrice(orderDetail.getTotalPrice().subtract(orderOldProduct.getPayAmount()));
                    orderDetail.setPayAmount(orderDetail.getTotalPrice().divide(new BigDecimal(orderOldProduct.getNum()),2,BigDecimal.ROUND_HALF_UP));

                    if (orderDetail.getTotalPrice().doubleValue() < 0)
                        throw new RemoteServiceException("请选择低于新机价格的旧机商品");
                }


                orderOldProducts.add(orderOldProduct);


            }

            orderOldProductService.lambdaUpdate().eq(OrderOldProduct::getOrderId,orderInfo.getOrderId()).remove();
            orderOldProductItemService.lambdaUpdate().eq(OrderOldProductItem::getOrderId,orderInfo.getOrderId()).remove();

            if (!CollectionUtils.isEmpty(orderOldProducts)){
                orderOldProductService.saveBatch(orderOldProducts);
            }

            if (!CollectionUtils.isEmpty(orderOldProductItems)){
                orderOldProductItemService.saveBatch(orderOldProductItems);
            }


        }

        orderInfo.insertOrUpdate();

        orderDetailService.lambdaUpdate().eq(OrderDetail::getOrderId,orderInfo.getOrderId()).remove();
        orderDetailService.saveBatch(orderDetails);

        List<OrderDetail> orderDetailList = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderInfo.getOrderId()).list();

        for (OrderDetail orderDetail : orderDetailList) {
            if (!StringUtil.isEmpty(orderDetail.getGoodsSpecId())) {
                GoodsSpec goodsSpec = goodsSpecService.getById(orderDetail.getGoodsSpecId());
                orderDetail.setGoodsMaterialId(goodsSpec.getGoodsCode());
                orderDetail.updateById();
            }
        }


        return orderInfo.getOrderId();
    }

    private OrderOldProductItem productCategoryItem(GoodsCategoryItem goodsCategoryItem) {
        OrderOldProductItem orderOldProductItem = BeanUtil.toBean(goodsCategoryItem, OrderOldProductItem.class);
        orderOldProductItem.setId(null);
        orderOldProductItem.setGoodsCategoryItemId(goodsCategoryItem.getId());
        return orderOldProductItem;
    }

    private void productCategory(OrderOldProduct orderOldProduct, GoodsCategoryItem goodsCategoryItem) {
        BeanUtil.copyProperties(goodsCategoryItem,orderOldProduct);
        orderOldProduct.setId(null);
        orderOldProduct.setPrice(goodsCategoryItem.getPrice());
        orderOldProduct.setSpecId(goodsCategoryItem.getId());
        orderOldProduct.setSpecName(goodsCategoryItem.getDictName());
    }


    private OrderDetail supplyOrderDetail(String orderId,GoodsMaterial gm,OrderDetail orderDetail){
        if (!StringUtils.equals(gm.getState(), StateEnum.ON.getKey())) {
            throw new RemoteServiceException("物料【" + gm.getGoodsName() + "】状态无效");
        }

        GoodsCategory goodsCategory = goodsCategoryService.getById(gm.getSmallId());
        if (goodsCategory == null) {
            throw new RemoteServiceException("小类【" + gm.getSmallName() + "】不存在");
        }

        List<GoodsMaterialItem> list = goodsMaterialItemService.lambdaQuery().eq(GoodsMaterialItem::getGoodsMaterialId, orderDetail.getGoodsMaterialId()).list();
        GoodsMaterial goodsMaterial = goodsMaterialService.getById(orderDetail.getGoodsMaterialId());
        if (goodsMaterial == null) {
            return orderDetail;
        }
        Integer insideQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.INSIDE.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);
        Integer outQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.OUT.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);
        Integer partsQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.PARTS.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);

        orderDetail.setOrderId(orderId);
        orderDetail.setBrandId(gm.getBrandId());
        orderDetail.setBrandName(gm.getBrandName());
        orderDetail.setMainNumber(gm.getMainId());
        orderDetail.setMainName(gm.getMainName());
        orderDetail.setSmallNumber(gm.getSmallId());
        orderDetail.setSmallName(gm.getSmallName());
        orderDetail.setGoodsName(gm.getGoodsName());
        orderDetail.setGoodsMaterialId(gm.getId());
        orderDetail.setGoodsSpecName(gm.getSpecsName());
        orderDetail.setImgUrl(goodsCategory.getImgUrl());
        orderDetail.setInsideNum(insideQty * orderDetail.getNum());
        orderDetail.setOutNum(outQty * orderDetail.getNum());
        orderDetail.setPartNum(partsQty * orderDetail.getNum());
        orderDetail.setGoodsMaterialId(gm.getId());
        orderDetail.setGoodsMaterialName(gm.getGoodsName());
        orderDetail.setGoodsMaterialSpecsName(gm.getSpecsName());
        orderDetail.setGoodsMaterialUnit(gm.getUnit());
        orderDetail.setIsVr(StringUtils.equals(gm.getIsVirtyual(), IsYesNoEnum.YES.getKey()));
        return orderDetail;
    }



    /**
     * 详情
     * @param orderId
     * @return
     */
    public OrderInfoDetailBean detail(String orderId){
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        List<OrderDetail> orderDetails = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderId).list();
        OrderInfoDetailBean orderInfoDetailBean = BeanUtil.copyProperties(orderInfo, OrderInfoDetailBean.class);

        List<GoodsMaterialStorage> goodsMaterialStorageList = goodsMaterialStorageService.lambdaQuery()
                .eq(GoodsMaterialStorage::getCompanyWechatId,orderInfo.getCompanyWechatId())
                .list();

        for(OrderDetail orderDetail : orderDetails){
            List<GoodsMaterialItem> list = goodsMaterialItemService.lambdaQuery().eq(GoodsMaterialItem::getGoodsMaterialId, orderDetail.getGoodsMaterialId()).list();
            GoodsMaterial goodsMaterial = goodsMaterialService.getById(orderDetail.getGoodsMaterialId());
            if(goodsMaterial == null){
                continue;
            }
            orderDetail.setGoodsMaterialStock(goodsMaterial.getStockQty());
            if(!StringUtils.equals(orderInfo.getOrderStatus(),OrderStatusEnum.NOPAY.toString())
                    && !StringUtils.equals(orderInfo.getOrderStatus(),OrderStatusEnum.DFH.toString())) {

                Integer insideQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.INSIDE.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);
                Integer outQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.OUT.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);
                Integer partsQty = list.stream().filter(v -> v.getType().equals(GoodsMaterialTypeEnum.PARTS.getKey())).map(GoodsMaterialItem::getQty).reduce(Integer::sum).orElse(0);

                orderDetail.setInsideNum(insideQty);
                orderDetail.setOutNum(outQty);
                orderDetail.setPartNum(partsQty);

                Integer integer = goodsMaterialStorageList.stream().filter(item -> item.getGoodsMaterialId().equals(goodsMaterial.getId())).map(GoodsMaterialStorage::getStockQty).reduce(Integer::sum)
                        .orElse(0);

                orderDetail.setStockQty(integer);
            }
        }
        orderInfoDetailBean.setPayType(orderInfo.getPayTypeId());
        orderInfoDetailBean.setOrderDetails(orderDetails);

        List<OrderOldProduct> list = orderOldProductService.lambdaQuery()
                .eq(OrderOldProduct::getOrderId, orderId).list();

        List<OrderOldProductDTO> orderOldProductDTOS = new ArrayList<>();

        for (OrderOldProduct orderOldProduct : list) {
            OrderOldProductDTO orderOldProductDTO = BeanUtil.toBean(orderOldProduct, OrderOldProductDTO.class);
            List<OrderOldProductItem> orderOldProductItemList = orderOldProductItemService.lambdaQuery().eq(OrderOldProductItem::getOrderOldProductId, orderOldProduct.getId()).list();
            orderOldProductDTO.setItemList(orderOldProductItemList);

            orderOldProductDTOS.add(orderOldProductDTO);
        }

        orderInfoDetailBean.setOrderOldProductDTOList(orderOldProductDTOS);


        return orderInfoDetailBean;
    }

    /**
     * 审核
     * @param orderId
     * @param examineStatus
     */
    public PayDetail examine(String orderId, ExamineStatusEnum examineStatus,String examineRemark,String ip) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        if(orderInfo == null){
            throw new RemoteServiceException("订单不存在");
        }
        if(orderInfo.getSaleType() != 2){
            throw new RemoteServiceException("非线下单不可审批");
        }
        if(!orderInfo.getOrderStatus().equals(OrderStatusEnum.NOPAY.toString())){
            throw new RemoteServiceException("非待支付订单不可审批");
        }
        if(!orderInfo.getExamineStatus().equals(ExamineStatusEnum.WAIT.getKey())){
            throw new RemoteServiceException("非待审批订单不可审批");
        }
        orderInfo.setExamineStatus(examineStatus.getKey());
        orderInfo.setExamineBy(adminUser.getNickName());
        orderInfo.setExamineRemark(examineRemark);
        orderInfo.setExamineTime(new Date());

        PayDetail payDetail = new PayDetail().setIsPay(false);
        if(examineStatus.getKey().equals(ExamineStatusEnum.OK.getKey())) {
            if (orderInfo.getPayTypeId().equals(PayTypeEnum.WECHAT.getKey())) {
                payDetail = wechatLogic.paymentNATIVE(orderId, orderInfo.getPayAmount(), "", "N", ip, orderInfo.getCompanyWechatId());
                //需要微信支付的单审批状态得等到支付成功后才能通过
                orderInfo.setExamineStatus(ExamineStatusEnum.WAIT.getKey());
                orderInfo.setExamineTime(null);
            } else {
                orderInfo.setOrderStatus(OrderStatusEnum.DFH.toString());
                orderInfo.setPayTime(new Date());
            }
        }
        orderInfo.updateById();

        return payDetail;
    }


}
