package com.gree.mall.miniapp.logic.es;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
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.miniapp.bean.PayDetail;
import com.gree.mall.miniapp.bean.es.EsOrderBuyBean;
import com.gree.mall.miniapp.bean.es.EsOrderInfoBean;
import com.gree.mall.miniapp.bean.es.EsOrderRefundBean;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.enums.*;
import com.gree.mall.miniapp.enums.es.ESGoodsStatusEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.ExpressLogic;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.logic.common.outside.WechatLogic;
import com.gree.mall.miniapp.logic.user.PayLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import com.gree.mall.miniapp.utils.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class OrderPayLogic {

    @Autowired
    EsGoodsService esGoodsService;

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    UserAddressService userAddressService;

    @Autowired
    UserService userService;

    @Autowired
    WechatLogic wechatLogic;

    @Autowired
    EsOrderInfoService esOrderInfoService;

    @Autowired
    ExpressLogic expressLogic;

    @Autowired
    EsOrderRefundFileService esOrderRefundFileService;

    @Autowired
    EsOrderRefundService esOrderRefundService;

    @Autowired
    EsGoodsImgService esGoodsImgService;

    @Autowired
    PayLogic payLogic;

    @Autowired
    CarouselMapService carouselMapService;


    public PayDetail buy(EsOrderBuyBean esOrderBuyBean, String ip, HttpServletRequest request) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        EsGoods esGoods = esGoodsService.getById(esOrderBuyBean.getEsGoodsId());
        EsGoodsImg esGoodsImg = esGoodsImgService.lambdaQuery().eq(EsGoodsImg::getEsGoodsId, esGoods.getId()).last("limit 1").one();

        if (!esGoods.getStatus().equals(ESGoodsStatusEnum.ON.getKey()) || esGoods.getDel())
            throw new RemoteServiceException("商品已下架");

        User user = userService.getById(esGoods.getUserId());

        if (user == null)
            throw new RemoteServiceException("卖家不存在");

        UserAddress userAddress = userAddressService.getById(esOrderBuyBean.getUserAddressId());

        EsOrderInfo esOrderInfo = new EsOrderInfo();
        esOrderInfo.setUserName(userAddress.getName());
        esOrderInfo.setEsOrderId("ES"+ IdWorker.getIdStr());
        esOrderInfo.setUserMobile(userAddress.getPhone());
        esOrderInfo.setPayType(esOrderBuyBean.getPayType());
        esOrderInfo.setProvince(userAddress.getProvince());
        esOrderInfo.setCity(userAddress.getCity());
        esOrderInfo.setArea(userAddress.getArea());
        esOrderInfo.setStreet(userAddress.getStreet());
        esOrderInfo.setReceAddress(userAddress.getAddress());
        esOrderInfo.setSellName(user.getNickName());
        esOrderInfo.setSellTime(esGoods.getCreateTime());
        esOrderInfo.setSellMobile(user.getMobile());
        esOrderInfo.setSellId(user.getUserId());

        esOrderInfo.setEsCategoryId(esGoods.getCategoryId());
        esOrderInfo.setEsCategoryName(esGoods.getCategoryName());
        esOrderInfo.setNum(esOrderBuyBean.getNum());
        esOrderInfo.setBrandName(esGoods.getBrand());
        esOrderInfo.setPower(esGoods.getPower());
        esOrderInfo.setProductionTime(esGoods.getMakeDate());
        esOrderInfo.setEnergyLabel(esGoods.getMark());
        esOrderInfo.setSaleType(1);
        esOrderInfo.setTotalAmount(esGoods.getPrice().multiply(Convert.toBigDecimal(esOrderBuyBean.getNum())));
        esOrderInfo.setWechatUserMobile(currentCompanyWechat.getUser().getMobile());
        esOrderInfo.setWechatUserName(currentCompanyWechat.getUser().getNickName());
        esOrderInfo.setWechatUserId(currentCompanyWechat.getUser().getUserId());
        esOrderInfo.setWechatUserUrl(currentCompanyWechat.getUser().getAvatar());
        esOrderInfo.setGoodsPrice(esGoods.getPrice());
        esOrderInfo.setEsGoodsId(esGoods.getId());
        esOrderInfo.setEsGoodsName(esGoods.getGoodsName());
        esOrderInfo.setGoodsUrl(esGoodsImg.getImgUrl());
        esOrderInfo.setSellUrl(esGoods.getUserHeadImg());
        esOrderInfo.setGoodsNote(esGoods.getGoodsNote());

        esOrderInfo.setProvinceId(userAddress.getProvinceId());
        esOrderInfo.setCityId(userAddress.getCityId());
        esOrderInfo.setAreaId(userAddress.getAreaId());
        esOrderInfo.setStreetId(userAddress.getStreetId());

        if (esOrderInfo.getNum() > esGoods.getQty()) {
            throw new RemoteServiceException("大于了上架数量");
        }


        String source = commonLogic.getSource();

        esOrderInfo.setSource(source.equals("B")?"公众号":"小程序");

        esOrderInfo.setCompanyName(currentCompanyWechat.getCompanyName());
        esOrderInfo.setCompanyWechatId(currentCompanyWechat.getCompanyWechatId());




        if (esOrderBuyBean.getPayType().equals(PayTypeEnum.WECHAT.getKey())) {

            esOrderInfo.setStatus(ExamineStatusEnum.SAVE.getKey());

            PayDetail payment = wechatLogic.payment(esOrderInfo.getEsOrderId(), esOrderInfo.getTotalAmount(),
                    source.equals("B") ? currentCompanyWechat.getUser().getOpenId() : currentCompanyWechat.getUser().getMiniOpenId(),
                    "N", ip,
                    currentCompanyWechat.getCompanyWechatId(), source.equals("A"));

            esOrderInfo.insert();
            return payment;
        }

        esOrderInfo.setStatus(ExamineStatusEnum.SAVE.getKey());
        esOrderInfo.setPayStatus(PayStatusEnum.PAID.getKey());

        esGoods.setStatus(ESGoodsStatusEnum.SALE.getKey());
        esGoods.updateById();

        carouselMapService.lambdaUpdate().eq(CarouselMap::getGoodsId,esGoods.getId())
                .set(CarouselMap::getState,0).update();


        esOrderInfo.insert();

        PayDetail payDetail = new PayDetail();
        payDetail.setIsPay(false);
        payDetail.setId(esOrderInfo.getEsOrderId());


        payLogic.sendMaterialExamineEsOrder(esOrderInfo.getEsOrderId());

        return payDetail;

    }

    public PayDetail waitPayOrder(String esOrderId, String ip) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);

        EsGoods esGoods = esGoodsService.getById(esOrderInfo.getEsGoodsId());


        DateTime dateTime = DateUtil.offsetMinute(esOrderInfo.getPayStartTime(), 10);


        if (new Date().after(dateTime))
            throw new RemoteServiceException("超过10分钟订单失败");
        if (!currentCompanyWechat.getUser().getUserId().equals(esOrderInfo.getWechatUserId()))
            throw new RemoteServiceException("订单支付有误");
        if (!esGoods.getStatus().equals(ESGoodsStatusEnum.ON.getKey()))
            throw new RemoteServiceException("商品非上架状态不可购买");

        String source = commonLogic.getSource();

        PayDetail payment = wechatLogic.payment(esOrderInfo.getEsOrderId(), esOrderInfo.getTotalAmount(),
                source.equals("B")  ? currentCompanyWechat.getUser().getOpenId() : currentCompanyWechat.getUser().getMiniOpenId(), "N", ip,
                currentCompanyWechat.getCompanyWechatId(), source.equals("A") );

        return payment;
    }

    public void notPay(String orderId, String ip) {
        EsOrderInfo esOrderInfo = esOrderInfoService.getById(orderId);
        if (!esOrderInfo.getStatus().equals(ExamineStatusEnum.SAVE.getKey()) && !esOrderInfo.getStatus().equals(ExamineStatusEnum.WAIT.getKey()))
            throw new RemoteServiceException("订单不属于待支付");

        if (esOrderInfo.getPayStatus().equals(PayStatusEnum.PAID.getKey())){
            EsGoods esGoods = esGoodsService.getById(esOrderInfo.getEsGoodsId());
            esGoods.setStatus(ESGoodsStatusEnum.ON.getKey());
            esGoods.updateById();


            carouselMapService.lambdaUpdate().eq(CarouselMap::getGoodsId,esGoods.getId())
                    .set(CarouselMap::getState,1).update();
        }

        esOrderInfoService.lambdaUpdate()
                .eq(EsOrderInfo::getEsOrderId,orderId)
                .set(EsOrderInfo::getStatus, PayStatusEnum.CANCEL.getKey())
                .set(EsOrderInfo::getPayStatus,"WAIT")
                .update();

    }

    public void send(String esOrderId, String pickType, String logisticsNo, String logisticsCode, String logisticsName) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);

        if (!(esOrderInfo.getSellId().equals(currentCompanyWechat.getUserId()) || currentCompanyWechat.getUser().getIsEs()))
            throw new RemoteServiceException("非发布人，不能发货");
        if (esOrderInfo.getStatus().equals("SEND") || esOrderInfo.getStatus().equals("OVER"))
            throw new RemoteServiceException("无需发货");

        if (!esOrderInfo.getStatus().equals("PAID"))
            throw new RemoteServiceException("无需发货");

        esOrderInfoService.lambdaUpdate().eq(EsOrderInfo::getEsOrderId,esOrderId)
                .set(EsOrderInfo::getStatus,"SEND")
                .set(EsOrderInfo::getPickType,pickType)
                .set(EsOrderInfo::getSendName,currentCompanyWechat.getUser().getNickName())
                .set(EsOrderInfo::getSendTime,new Date())
                .set(!StringUtil.isEmpty(logisticsNo),EsOrderInfo::getLogisticsNo,logisticsNo)
                .set(!StringUtil.isEmpty(logisticsCode),EsOrderInfo::getLogisticsCode,logisticsCode)
                .set(!StringUtil.isEmpty(logisticsName),EsOrderInfo::getLogisticsName,logisticsName).update();

        //订阅物流
        if (!StringUtil.isEmpty(logisticsNo)) {
            expressLogic.subscribeExpress(logisticsNo, logisticsCode);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void payPrice(String esOrderId, BigDecimal price, String fileUrl, String remark) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        EsOrderPrice esOrderPrice = new EsOrderPrice();
        esOrderPrice.setEsOrderInfoId(esOrderId);
        esOrderPrice.setPrice(price);
        esOrderPrice.setFileUrl(fileUrl);
        esOrderPrice.setRemark(remark);
        esOrderPrice.insert();

        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);

        if (!(esOrderInfo.getSellId().equals(currentCompanyWechat.getUserId()) || currentCompanyWechat.getUser().getIsEs()))
            throw new RemoteServiceException("非发布人，不能确认");

        if (!(esOrderInfo.getStatus().equals("SAVE") && esOrderInfo.getSaleType().equals(1) && esOrderInfo.getPayType().equals(PayTypeEnum.CASH.getKey())))
            throw new RemoteServiceException("不可确认收款");


        esOrderInfoService.lambdaUpdate().eq(EsOrderInfo::getEsOrderId,esOrderId)
                .set(EsOrderInfo::getStatus,"PAID")
                .set(EsOrderInfo::getPayStatus,"PAID")
                .set(EsOrderInfo::getPayTime,new Date())
                .update();
    }

    public IPage<EsOrderInfo> list(HttpServletRequest request, String esGoodsName, String orderId, String sellName, String userName, String userMobile, String sellMobile, List<String> status, String startCreateTime, String endCreateTime, String startPayTime, String endPayTime, Integer pageNum, Integer pageSize) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        return esOrderInfoService.lambdaQuery().eq(!StringUtil.isEmpty(esGoodsName), EsOrderInfo::getEsGoodsName, esGoodsName)
                .eq(!StringUtil.isEmpty(orderId), EsOrderInfo::getEsOrderId, orderId)
                .and(!StringUtil.isEmpty(currentCompanyWechat.getUserId()), item ->
                                item.eq(EsOrderInfo::getWechatUserId, currentCompanyWechat.getUser().getUserId())
                        .or().eq(!StringUtil.isEmpty(currentCompanyWechat.getUser().getMobile()),
                                        EsOrderInfo::getUserMobile,currentCompanyWechat.getUser().getMobile())
                )
                .eq(!StringUtil.isEmpty(sellName), EsOrderInfo::getSellName, sellName)
                .eq(!StringUtil.isEmpty(userName), EsOrderInfo::getUserName, userName)
                .eq(!StringUtil.isEmpty(userMobile), EsOrderInfo::getUserMobile, userMobile)
                .eq(!StringUtil.isEmpty(sellMobile), EsOrderInfo::getSellMobile, sellMobile)
                .in(!CollectionUtils.isEmpty(status) && !status.contains("REFUND") && !status.contains("CANCEL"), EsOrderInfo::getStatus, status)
                .in(!CollectionUtils.isEmpty(status) && status.contains("REFUND"), EsOrderInfo::getStatus, "WAIT_REFUND","CANCEL")
                .in(!CollectionUtils.isEmpty(status) && status.contains("REFUND"), EsOrderInfo::getPayStatus, "PAID")
                .in(!CollectionUtils.isEmpty(status) &&  status.contains("CANCEL"), EsOrderInfo::getStatus, status)
                .in(!CollectionUtils.isEmpty(status) &&  status.contains("CANCEL"), EsOrderInfo::getPayStatus, "WAIT")
                .in(!StringUtil.isEmpty(currentCompanyWechat.getCurrentCompanyWechatId()), EsOrderInfo::getCompanyWechatId, currentCompanyWechat.getCurrentCompanyWechatId())
                .between(!StringUtil.isEmpty(startCreateTime), EsOrderInfo::getCreateTime, startCreateTime, endCreateTime)
                .between(!StringUtil.isEmpty(startPayTime), EsOrderInfo::getPayTime, startPayTime, endPayTime)
                .orderByDesc(EsOrderInfo::getCreateTime)
                .page(new Page<>(pageNum, pageSize));
    }

    public EsOrderInfoBean detail(String esOrderId) {
        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);
        EsOrderInfoBean esOrderInfoBean = BeanUtil.toBean(esOrderInfo, EsOrderInfoBean.class);

        EsOrderRefund esOrderRefund = esOrderRefundService.lambdaQuery().eq(EsOrderRefund::getEsOrderId, esOrderInfo.getEsOrderId())
                .eq(EsOrderRefund::getRefundSalesType, 1).last("limit 1").one();

        List<EsOrderRefund> list = esOrderRefundService.lambdaQuery().eq(EsOrderRefund::getEsOrderId, esOrderInfo.getEsOrderId())
                .eq(EsOrderRefund::getStatus, "OVER").list();


        if (!CollectionUtils.isEmpty(list)) {
            List<EsOrderRefundBean> esOrderRefundBeans = BeanUtil.copyToList(list, EsOrderRefundBean.class);
            for (EsOrderRefundBean esOrderRefundBean : esOrderRefundBeans) {
                List<EsOrderRefundFile> esOrderRefundFiles = esOrderRefundFileService.lambdaQuery().eq(EsOrderRefundFile::getEsOrderRefundId, esOrderRefundBean.getEsOrderRefundId()).list();
                esOrderRefundBean.setEsOrderRefundFileList(esOrderRefundFiles);

            }
            esOrderInfoBean.setEsOrderRefundList(esOrderRefundBeans);
        }

        if (esOrderRefund != null) {
            EsOrderRefundBean esOrderRefundBean = BeanUtil.toBean(esOrderRefund, EsOrderRefundBean.class);

            List<EsOrderRefundFile> esOrderRefundFiles = esOrderRefundFileService
                    .lambdaQuery().eq(EsOrderRefundFile::getEsOrderRefundId, esOrderRefund.getEsOrderRefundId()).list();

            esOrderRefundBean.setEsOrderRefundFileList(esOrderRefundFiles);

            esOrderInfoBean.setEsOrderRefunds(esOrderRefundBean);
        }


        return esOrderInfoBean;
    }

    public void refund(String esOrderId, String refundType, List<String> fileUrls,String refundNote) {
        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);

        EsOrderRefund esOrderRefund = BeanUtil.toBean(esOrderInfo, EsOrderRefund.class);


        esOrderRefund.setEsOrderId(esOrderId);
        esOrderRefund.setRefundType(refundType);
        esOrderRefund.setRefundNote(refundNote);

        esOrderRefund.setStatus("WAIT");
        esOrderRefund.insert();

        esOrderInfo.setStatus("WAIT_REFUND");
        esOrderInfo.updateById();

        List<EsOrderRefundFile> esOrderRefundFiles = new ArrayList<>();

        for (String fileUrl : fileUrls) {
            EsOrderRefundFile esOrderRefundFile = new EsOrderRefundFile();
            esOrderRefundFile.setEsOrderRefundId(esOrderRefund.getEsOrderRefundId());
            esOrderRefundFile.setFileUrl(fileUrl);
            esOrderRefundFiles.add(esOrderRefundFile);
        }

        esOrderRefundFileService.saveBatch(esOrderRefundFiles);

    }

    public IPage<EsOrderRefund> listRefund(HttpServletRequest request, String esGoodsName, String orderId, String sellName, String userName,
                                           String userMobile, String sellMobile, List<String> status, String startCreateTime, String endCreateTime, String startPayTime, String endPayTime, Integer pageNum, Integer pageSize) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        return esOrderRefundService.lambdaQuery().eq(!StringUtil.isEmpty(esGoodsName), EsOrderRefund::getEsGoodsName, esGoodsName)
                .eq(!StringUtil.isEmpty(orderId), EsOrderRefund::getEsOrderId, orderId)
                .eq(!StringUtil.isEmpty(sellName), EsOrderRefund::getSellName, sellName)
                .eq(!StringUtil.isEmpty(userName), EsOrderRefund::getUserName, userName)
                .eq(!StringUtil.isEmpty(userMobile), EsOrderRefund::getUserMobile, userMobile)
                .eq(!StringUtil.isEmpty(sellMobile), EsOrderRefund::getSellMobile, sellMobile)
                .in(!CollectionUtils.isEmpty(status), EsOrderRefund::getStatus, status)
                .in(!StringUtil.isEmpty(currentCompanyWechat.getCurrentCompanyWechatId()), EsOrderRefund::getCompanyWechatId, currentCompanyWechat.getCurrentCompanyWechatId())
                .between(!StringUtil.isEmpty(startCreateTime), EsOrderRefund::getCreateTime, startCreateTime, endCreateTime)
                .between(!StringUtil.isEmpty(startPayTime), EsOrderRefund::getPayTime, startPayTime, endPayTime)
                .page(new Page<>(pageNum, pageSize));
    }

    public void okSend(String esOrderId) {

        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);

        if (!esOrderInfo.getStatus().equals("SEND"))
            throw new RemoteServiceException("订单不属于已发货");

        esOrderInfoService.lambdaUpdate().eq(EsOrderInfo::getEsOrderId,esOrderId)
                .set(EsOrderInfo::getStatus,"OVER")
                .update();

    }

    public void payOk(String esOrderId) {
        EsOrderInfo esOrderInfo = esOrderInfoService.getById(esOrderId);
        if (!esOrderInfo.getStatus().equals(ExamineStatusEnum.WAIT.getKey()))
            throw new RemoteServiceException("非待确认");


        esOrderInfoService.lambdaUpdate().eq(EsOrderInfo::getEsOrderId,esOrderId)
                .eq(EsOrderInfo::getStatus,ExamineStatusEnum.WAIT.getKey())
                .set(EsOrderInfo::getStatus,"PAID")
                .set(EsOrderInfo::getPayStatus,"PAID")
                .update();

    }
}
