package cn.pluss.platform.device.impl;

import cn.pluss.platform.ali.AliService;
import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.device.DeviceSpecService;
import cn.pluss.platform.device.MercOrderDetailService;
import cn.pluss.platform.device.MercOrderNewService;
import cn.pluss.platform.device.MercShopTrolleyService;
import cn.pluss.platform.deviceDetail.DeviceDetailService;
import cn.pluss.platform.dto.MercOrderNewDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.enums.DeviceOrderStatus;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.*;
import cn.pluss.platform.openAccount.OpenAccountRecordService;
import cn.pluss.platform.pay.PayService;
import cn.pluss.platform.postageConfig.PostageConfigService;
import cn.pluss.platform.systemConfig.SystemConfigService;
import cn.pluss.platform.userAddress.UserAddressService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.util.ParametersUtil;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.vo.MercOrderExpressVO;
import cn.pluss.platform.vo.MercOrderNewVO;
import cn.pluss.platform.yinsheng.YsOldSrcMerchantNo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;

/**
 * <p>
 * 新的订单表 服务实现类
 * </p>
 *
 * @author Djh
 * @since 2022-03-17
 */
@Service
public class MercOrderNewServiceImpl extends ServiceImpl<MercOrderNewMapper, MercOrderNew> implements MercOrderNewService {

    @Resource
    private UserAppService userAppService;

    @Autowired
    private UserAddressService userAddressService;

    @Autowired
    private MercShopTrolleyService mercShopTrolleyService;

    @Autowired
    private DeviceSpecService deviceSpecService;

    @Autowired
    private DeviceDetailService deviceDetailService;

    @Autowired
    private MercOrderDetailService mercOrderDetailService;

    @Resource
    private MercOrderExpressDetailMapper mercOrderExpressDetailMapper;

    @Resource
    private MercOrderExpressMapper mercOrderExpressMapper;

    @Resource
    private PostageConfigService postageConfigService;

    @Resource
    private SystemConfigService systemConfigService;

    @Resource
    private MerchantBaseInfoMapper mbiMapper;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private AliService aliService;

    @Resource
    private MerchantOrderMapper merchantOrderMapper;

    @Autowired
    private MerchantChannelStatusMapper mcsMapper;

    @Setter(onMethod_ = {@Autowired, @Qualifier("ysPayOldService")})
    private PayService ysPayOldService;

    @Resource
    private OpenAccountRecordService openAccountRecordService;

    @Resource
    private MerchantBaseInfoMapper merchantBaseInfoMapper;

    @Resource
    private MerchantStoreMapper merchantStoreMapper;

    /**
     * 设备订单分页查询
     *
     * @param page
     * @param condition
     * @return
     */
    @Override
    public Page<MercOrderNewVO> pageInfo(Page<MercOrderNewVO> page, MercOrderNewVO condition) {
        return baseMapper.pageInfo(page, condition);
    }

    /**
     * 确认收货
     *
     * @param id
     */
    @Override
    public void receiving(Long id) {
        UserApp userApp = userAppService.queryUserAppByToken();
        MsgException.checkNull(userApp, "登录用户异常");
        MercOrderNew order = baseMapper.selectById(id);
        MsgException.checkNull(order, "订单数据异常");
        order.setStatus("04");
        baseMapper.updateById(order);
    }

    /**
     * 获取订单的物流信息
     *
     * @param id
     * @return
     */
    @Override
    public MercOrderExpressVO getOrderExpressInfo(Long id) {
        MercOrderDetail detail = mercOrderDetailService.getById(id);
        MsgException.checkNull(detail, "订单详情数据异常");
        MsgException.checkBlank(detail.getExpressNo(), "暂无物流信息");
        MercOrderExpressVO vo = mercOrderExpressMapper.getByExpressNo(detail.getExpressNo());
        if (vo != null) {
            List<MercOrderExpressDetail> list = mercOrderExpressDetailMapper.getByExpressNo(detail.getExpressNo());
            vo.setExpressDetailList(list);
        }
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object apiCreateOrder(MercOrderNewDTO orderNewDTO) {
        UserApp userApp = userAppService.queryUserAppByToken();
        orderNewDTO.setUserId(userApp.getUserId());
        return createOrder(orderNewDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object createOrder(MercOrderNewDTO orderNewDTO) {

        // 生成订单数据
        MercOrderNew mercOrderNew = new MercOrderNew();
        mercOrderNew.setStatus(MercOrderNew.STATUS_NO_PAY);
        mercOrderNew.setUserId(orderNewDTO.getUserId());
        mercOrderNew.setOrderNo(UUID.randomUUID().toString().replace("-", ""));
        mercOrderNew.setPayType(orderNewDTO.getPayType());

        UserAddress address = userAddressService.getById(orderNewDTO.getAddressId());
        mercOrderNew.setReceiver(address.getName());
        mercOrderNew.setPhone(address.getPhone());
        mercOrderNew.setAreaName(address.getAreaName());
        mercOrderNew.setAddress(address.getAddress());

        if (orderNewDTO.getItemList() == null || orderNewDTO.getItemList().isEmpty()) {
            throw new MsgException("缺少商品信息");
        }

        // 计算价格
        LambdaQueryWrapper<MercShopTrolley> qWrapper = Wrappers.lambdaQuery();
        qWrapper.in(MercShopTrolley::getId, orderNewDTO.getItemList());

        List<MercShopTrolley> mercShopTrolleyList = mercShopTrolleyService.list(qWrapper);

        BigDecimal priceAmt = BigDecimal.ZERO;
        BigDecimal postage = BigDecimal.ZERO;
        for (MercShopTrolley item : mercShopTrolleyList) {
            MercOrderDetail mercOrderDetail = new MercOrderDetail();
            mercOrderDetail.setStatus(MercOrderDetail.STATUS_NO_PAY);
            mercOrderDetail.setCode(item.getCode());
            mercOrderDetail.setUserId(item.getUserId());
            mercOrderDetail.setShopTrolleyId(item.getId());
            mercOrderDetail.setDeviceLogo(item.getDeviceLogo());
            mercOrderDetail.setName(item.getName());
            mercOrderDetail.setNum(item.getNum());
            mercOrderDetail.setOrderNo(mercOrderNew.getOrderNo());
            mercOrderDetail.setType(item.getType());

            DeviceDetail deviceDetail = deviceDetailService.getByCodeAndSpec(item.getCode(), item.getType());
            if (item.getNum() >= deviceDetail.getWholesaleMinNum()) {
                mercOrderDetail.setPrice(deviceDetail.getWholesalePrice());
                priceAmt = priceAmt.add(deviceDetail.getWholesalePrice().multiply(BigDecimal.valueOf(item.getNum())));
            } else {
                mercOrderDetail.setPrice(deviceDetail.getUnitPrice());
                priceAmt = priceAmt.add(deviceDetail.getUnitPrice().multiply(BigDecimal.valueOf(item.getNum())));
            }
            DeviceSpec spec = deviceSpecService.getByCodeAndSpec(item.getCode(), item.getType());
            MsgException.checkNull(spec, "商品规格异常");
            BigDecimal ownFee = BigDecimal.ZERO;
            if (!DeviceSpec.POSTAGE_YES.equals(spec.getPostageFlag())) {
                ownFee = postageConfigService.getGoodPostageInfo(address, spec.getWeight());
                postage = postage.add(ownFee);
            }
            mercOrderDetail.setPostage(ownFee);
            // 同时保存商品详情的价格
            mercOrderDetailService.save(mercOrderDetail);
        }
        if (orderNewDTO.getPostage() == null) {
            mercOrderNew.setPostage(postage);
        }
        mercOrderNew.setOrderAmt(priceAmt.add(postage));
        if (orderNewDTO.getTicketId() != null) {
            // 优惠券
        } else {
            mercOrderNew.setDiscountAmt(BigDecimal.ZERO);
            mercOrderNew.setActualAmt(priceAmt.add(postage));
        }

        mercOrderNew.setCreateTime(new Date());
        mercOrderNew.setCreator(orderNewDTO.getUserId());
        mercOrderNew.setUpdateTime(new Date());

        String type = systemConfigService.querySystemConfigValue(Constant.PAYMENT_CHANNEL_TYPE);
        Integer channel = Constant.DEFAULT_CHANNEL;
        if ("1".equals(type)) {
            //原生通道类型
            channel = Constant.PRIMORDIAL_CHANNEL;
            if (!Constant.PAY_TYPE_ALIPAY.equals(orderNewDTO.getPayType())) {
                MsgException.throwException("暂不支持微信支付，请使用支付宝支付");
            }
        }
        //获取收款账号
        String merchantCode = systemConfigService.querySystemConfigValue(Constant.SYSTEM_MERCHANT_KEY);
        if (StringUtil.isEmpty(merchantCode)) {
            merchantCode = Constant.DEFUALT_CASHIER_MERCHANT;
        }
        MerchantBaseInfo merchant = mbiMapper.queryByMerchantCode(merchantCode);
        MsgException.checkNull(merchant, "收款商户信息异常");

        mercOrderNew.setMerchantName(merchant.getAlias());
        mercOrderNew.setMerchantCode(merchant.getMerchantCode());
        //默认是银盛通道
        mercOrderNew.setChannel(channel);

        save(mercOrderNew);

        JSONObject result = new JSONObject(3);
        result.put("orderNo", mercOrderNew.getOrderNo());
        //类型 type 1：H5 2:为小程序 3：走原生通道
        if (Constant.PRIMORDIAL_CHANNEL.equals(mercOrderNew.getChannel())) {
            result.put("type", "3");
            Map<String, String> map = new HashMap<>(16);
            map.put("body", "收银呗商城");
            map.put("subject", "收银呗商城");
            map.put("outTradeNo", mercOrderNew.getOrderNo());
            map.put("totalAmount", mercOrderNew.getActualAmt().toPlainString());
            Map<String, Object> payParam = aliService.appPayParam(map);
            if (payParam == null || StringUtil.isEmpty(payParam.get("aliCode"))) {
                MsgException.throwException("支付宝下单异常！");
            }
            result.put("aliCode", payParam.get("aliCode"));
            return result;
        }
        result.put("type", "1");
        if (Constant.PAY_TYPE_ALIPAY.equals(orderNewDTO.getPayType())) {
            // TODO 生成支付宝订单数据，并返回给APP
            String payUrl = ParametersUtil.domain + "/wap/aliPay/returnUrl?orderNumber=" + mercOrderNew.getOrderNo();
            try {
                String pUrl = URLDecoder.decode(payUrl, "UTF-8");
                result.put("payUrl", Constant.ALIPAY_H5_PAY_URL_PRIFIX + pUrl);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else {
            result.put("type", "2");
            // TODO 生成微信支付订单数据，并将小程序付款路径返回到APP中
            MerchantChannelStatus channelStatus = mcsMapper.getByMerchantCode(merchantCode, channel);
            String ghId = YsOldSrcMerchantNo.RSCY.getDefGhId();
            if(channelStatus != null){
                ghId = YsOldSrcMerchantNo.getGhIdByValue(channelStatus.getSrcMerchantNo());
            }
            result.put("ghId", ghId);
            result.put("path", "pages/pay/index?orderId=" + mercOrderNew.getOrderNo());
        }
        return result;
    }

    /**
     * 获取邮费信息
     *
     * @param orderNewDTO
     * @return
     */
    @Override
    public Object getOrderPostageInfo(MercOrderNewDTO orderNewDTO) {
        List<Long> itemList = orderNewDTO.getItemList();
        if (itemList == null || itemList.size() <= 0) {
            MsgException.throwException("缺少商品信息");
        }
        MsgException.checkNull(orderNewDTO.getAddressId(), "请先选择地址");
        Long addressId = orderNewDTO.getAddressId();
        UserAddress address = userAddressService.getById(addressId);
        MsgException.checkNull(address, "地址信息异常");
        List<MercShopTrolley> list = mercShopTrolleyService.listByIds(itemList);
        if (list == null || list.size() <= 0) {
            MsgException.throwException("购物车数据异常");
        }
        return calcPostage(address, list);
    }

    /**
     * 获取订单邮费
     *
     * @param address
     * @param list
     * @return
     */
    public BigDecimal calcPostage(UserAddress address, List<MercShopTrolley> list) {
        BigDecimal postage = BigDecimal.ZERO;
        for (MercShopTrolley mst : list) {
            DeviceSpec item = deviceSpecService.getByCodeAndSpec(mst.getCode(), mst.getType());
            MsgException.checkNull(item, "商品规格异常");
            if (!DeviceSpec.POSTAGE_YES.equals(item.getPostageFlag())) {
                BigDecimal fee = postageConfigService.getGoodPostageInfo(address, item.getWeight().multiply(BigDecimal.valueOf(mst.getNum())));
                postage = postage.add(fee);
            }
        }
        return postage;
    }

    /**
     * 根据订单号查询订单信息
     *
     * @param orderNumber
     * @return
     */
    @Override
    public MercOrderNew getOrderByNo(String orderNumber) {
        return baseMapper.getOrderByNo(orderNumber);
    }

    @Override
    public void proPayCallback(MercOrderNew newOrder, Date transDt, String transNo, String thirdTransNo) {
        if (!DeviceOrderStatus.WAIT_PAY.getStatus().equals(newOrder.getStatus())) {
            return;
        }
        newOrder.setThirdTransNo(thirdTransNo);
        newOrder.setTransNo(transNo);
        newOrder.setTransDt(transDt);

    }

    /**
     * 设备商城支付回调V2
     *
     * @param orderNo
     * @param tradeNo
     * @param thridTradeNo
     * @param transDt
     */
    @Override
    public void devicePaySuccessNotifyV2(String orderNo, String tradeNo, String thridTradeNo, Date transDt, MercOrderNew order) {
        if (order == null) {
            order = baseMapper.getOrderByNo(orderNo);
        }
        if (order == null || !DeviceOrderStatus.WAIT_PAY.getStatus().equals(order.getStatus())) {
            return;
        }
        order.setTransNo(tradeNo);
        order.setThirdTransNo(thridTradeNo);
        order.setTransDt(transDt);
        order.setStatus(DeviceOrderStatus.SUCC_PAY.getStatus());
        baseMapper.updateById(order);

        UpdateWrapper<MercOrderDetail> updateWrapper = new UpdateWrapper<MercOrderDetail>()
                .eq("orderNo", order.getOrderNo()).set("status", DeviceOrderStatus.SUCC_PAY.getStatus());
        mercOrderDetailService.update(updateWrapper);

        // 清除购物车的数据
        LambdaQueryWrapper<MercOrderDetail> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(MercOrderDetail::getOrderNo, orderNo);
        List<MercOrderDetail> orderDetailList = mercOrderDetailService.list(qWrapper);

        List<Long> shopTrolleyIdList = new ArrayList<>();
        for (MercOrderDetail item : orderDetailList) {
            shopTrolleyIdList.add(item.getShopTrolleyId());
        }

        LambdaQueryWrapper<MercShopTrolley> qWrapper2 = Wrappers.lambdaQuery();
        qWrapper2.in(MercShopTrolley::getId, shopTrolleyIdList);
        mercShopTrolleyService.remove(qWrapper2);

        if(StringUtil.isNotEmpty(order.getMerchantCode())){
            //插入订单表数据
            MerchantStore store = merchantStoreMapper.getStoreByMerchantCode(order.getMerchantCode());
            MerchantOrder mOrder = new MerchantOrder();
            mOrder.convert(order,store);
            merchantOrderMapper.insert(mOrder);
        }

        //设备商城 判断商户符合开户奖
        List<MerchantBaseInfo> merchantList = merchantBaseInfoMapper.selectListByUserId(order.getUserId());
        if(merchantList.isEmpty()){
            return;
        }
        List<MercOrderDetail> odList =  mercOrderDetailService.listByOrderNoAndCode(order.getOrderNo(),"libao");
        if(odList.isEmpty()){
            return;
        }
        openAccountRecordService.operatAccountOpen(odList.get(0),merchantList.get(0));
    }

    /**
     * 查询订单支付状态
     *
     * @param orderNewDTO
     * @return
     */
    @Override
    public Object getOrderStatusInfo(MercOrderNewDTO orderNewDTO) {
        MsgException.checkNull(orderNewDTO.getOrderNo(), "订单号为空，查询失败");
        MercOrderNew order = baseMapper.getOrderByNo(orderNewDTO.getOrderNo());
        JSONObject result = new JSONObject(2);
        result.put("status", DeviceOrderStatus.SUCC_PAY.getStatus());
        result.put("orderNo", orderNewDTO.getOrderNo());
        if (DeviceOrderStatus.SUCC_PAY.getStatus().equals(order.getStatus())) {
            return result;
        }
        Integer channel = order.getChannel();
        MsgException.checkNull(channel, "未知通道");
        switch (channel) {
            case 4:
                //银盛通道
                MerchantChannelStatus channelStatus = mcsMapper.getByMerchantCode(order.getMerchantCode(), channel);
                MsgException.checkNull(channelStatus, "当前通道信息异常！");
                MerchantOrder mo = new MerchantOrder();
                order.convert(mo, null);
                JSONObject resp = ysPayOldService.tradeQuery(mo, channelStatus.getMerchantId());
                if (ResultCode.FAIL.code() == resp.getIntValue("code")) {
                    MsgException.throwException("查询失败：失败原因:" + resp.getString("msg"));
                }
                String payStatus = resp.getString("payStatus");
                if (!"1".equals(payStatus)) {
                    result.put("status", DeviceOrderStatus.WAIT_PAY.getStatus());
                }
                break;
            case 5:
                //官方通道
                MsgException.throwException("官方通道订单状态，自行确认");
                break;
            default:
                MsgException.throwException("通道类型异常！");
                break;
        }
        return result;
    }
}
