package com.sptg.pay.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.netflix.discovery.util.StringUtil;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.estate.api.dto.FaceChargeProjectResidentialUserDto;
import com.sptg.estate.api.dto.UserDto;
import com.sptg.estate.api.entity.*;
import com.sptg.estate.api.feigns.*;
import com.sptg.pay.api.dto.PayCertificateDto;
import com.sptg.pay.api.dto.PayChannelConfigDto;
import com.sptg.pay.api.dto.UserOrderDto;
import com.sptg.pay.api.entity.PayCertificate;
import com.sptg.pay.api.entity.PayChannelConfig;
import com.sptg.pay.api.entity.UserOrder;
import com.sptg.pay.api.vo.AjaxResult;
import com.sptg.pay.biz.mapper.UserOrderMapper;
import com.sptg.pay.biz.service.PayChannelConfigServiceInterface;
import com.sptg.pay.biz.service.UserOrderServiceInterface;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author zwx
 * @create 2020/5/16 9:56
 */
@Service
@RequiredArgsConstructor
public class UserOrderServiceImpl extends ServiceImpl<UserOrderMapper, UserOrder> implements UserOrderServiceInterface {

    private final PayChannelConfigServiceInterface payChannelConfigServiceInterface;
    private final UserFeign userFeign;
    private final FaceChargeProjectFeign faceChargeProjectFeign;
    private final ResidentialFeign residentialFeign;
    private final UnitFeign unitFeign;
    private final RoomFeign roomFeign;
    private final FaceChargeProjectResidentialUserFeign faceChargeProjectResidentialUserFeign;
    public final static String WXPAY = "wxPay";
    public final static String ALIPAY = "aliPay";

    @Override
    public ResultBean<Page<UserOrder>> showUserOrderPage(UserOrderDto userOrderDto) {
        // 构建查询条件
        Wrapper<UserOrder> wrapper = new EntityWrapper<>();
        if (StringUtils.isNotEmpty(userOrderDto.getBizOrderNo())) {
            wrapper.eq("s_biz_order_no", userOrderDto.getBizOrderNo());
        }
        if (StringUtils.isNotEmpty(userOrderDto.getOrderType())) {
            wrapper.eq("s_order_type", userOrderDto.getOrderType());
        }
        if (null != userOrderDto.getIsCharge()) {
            wrapper.eq("i_is_charge", userOrderDto.getIsCharge());
        }
        if (null != userOrderDto.getPayStatus()) {
            wrapper.eq("i_pay_status", userOrderDto.getPayStatus());
        }
        if (StringUtils.isNotEmpty(userOrderDto.getPayType())) {
            wrapper.eq("s_pay_type", userOrderDto.getPayType());
        }
        if (null != userOrderDto.getResidentialId()) {
            wrapper.eq("l_residential_id", userOrderDto.getResidentialId());
        }
        if (null != userOrderDto.getUnitId()) {
            wrapper.eq("l_unit_id", userOrderDto.getUnitId());
        }
        if (null != userOrderDto.getRoomId()) {
            wrapper.eq("l_room_id", userOrderDto.getRoomId());
        }
        if (StringUtils.isNotEmpty(userOrderDto.getName())) {
            wrapper.eq("s_name", userOrderDto.getName());
        }
        if (StringUtils.isNotEmpty(userOrderDto.getTel())) {
            wrapper.eq("s_tel", userOrderDto.getTel());
        }
        if (null != userOrderDto.getStartDateCondition()) {
            wrapper.ge("t_create_date", userOrderDto.getStartDateCondition());
        }
        if (null != userOrderDto.getEndDateCondition()) {
            wrapper.le("t_create_date", userOrderDto.getEndDateCondition());
        }
        //过滤删除
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        //  排序字段
        if (userOrderDto.getSortField() != null && userOrderDto.getSortOrder() != null){
            wrapper.orderBy(userOrderDto.getSortField(),userOrderDto.getSortOrder().equals("asc"));
        }else {
            //  排序字段 时间降序
            wrapper.orderBy("t_create_date",false);
        }
        return new ResultBean<>(ResultEnum.SUCCESS, this.selectPage(userOrderDto.getPage(), wrapper));
    }

    @Override
    public List<UserOrder> getUserOrderList(UserOrderDto userOrderDto) {
        Wrapper<UserOrder> wrapper = new EntityWrapper<>();
        //支付状态
        wrapper.eq("pay_status", userOrderDto.getPayStatus());
        return this.selectList(wrapper);
    }

    @Override
    public ResultBean<UserOrder> addUserOrder(UserOrderDto userOrderDto) {
        Date today = new Date();
        userOrderDto.setCreateDate(today);
        userOrderDto.setUpdateDate(today);
        userOrderDto.setPayStatus(OperationConstant.ONE); //未付款
        String bizOrderNo = genBizOrderNo(); //构建订单号
        userOrderDto.setBizOrderNo(bizOrderNo); //人脸订单
        User user = userFeign.findUserById(userOrderDto.getUserId()); //获取用户信息
        userOrderDto.setResidentialName(user.getResidentialName());
        userOrderDto.setResidentialId(user.getResidentialId());
        userOrderDto.setUnitName(user.getUnitName());
        userOrderDto.setUnitId(user.getUnitId());
        userOrderDto.setRoomName(user.getRoomName());
        userOrderDto.setRoomId(user.getRoomId());
        userOrderDto.setName(user.getName());
        userOrderDto.setTel(user.getTel());
        if (this.insert(userOrderDto)) {
            //处理estate_face_charge_project_residential_user表
            FaceChargeProjectResidentialUserDto faceChargeProjectResidentialUserDto = new FaceChargeProjectResidentialUserDto();
            faceChargeProjectResidentialUserDto.setCreateDate(today);
            faceChargeProjectResidentialUserDto.setFaceChargeId(userOrderDto.getGoodsId());
            faceChargeProjectResidentialUserDto.setResidentialId(user.getResidentialId());
            faceChargeProjectResidentialUserDto.setUserId(userOrderDto.getUserId());
            if (userOrderDto.getFeeType().equals("试用")) {
                faceChargeProjectResidentialUserDto.setTypeItem(11);
            }
            if (userOrderDto.getFeeType().equals("长期")) {
                faceChargeProjectResidentialUserDto.setTypeItem(12);
            }
            if (userOrderDto.getFeeType().equals("押金")) {
                faceChargeProjectResidentialUserDto.setTypeItem(21);
            }
            if (userOrderDto.getFeeType().equals("套餐")) {
                faceChargeProjectResidentialUserDto.setTypeItem(22);
            }
            ResultBean<Boolean> bean = faceChargeProjectResidentialUserFeign.addFaceChargeProjectResidentialUser(faceChargeProjectResidentialUserDto);
            if (!bean.getData()) {
                return new ResultBean<>(ResultEnum.ERROR);
            }
            UserOrder userOrder = new UserOrder();
            BeanUtils.copyProperties(userOrderDto, userOrder);
            return new ResultBean<>(ResultEnum.SUCCESS, userOrder);
        }
        return new ResultBean<>(ResultEnum.ERROR, null);
    }

    @Override
    public ResultBean<Boolean> updateUserOrder(UserOrder userOrder) {
        boolean result = this.updateById(userOrder);
        if (result) {
            return new ResultBean<>(ResultEnum.SUCCESS, result);
        }
        return new ResultBean<>(ResultEnum.ERROR, result);
    }

    @Override
    public UserOrder findUserOrderById(Long id) {
        Wrapper<UserOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("l_id", id);
        //过滤删除
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return this.selectOne(wrapper);
    }

    @Override
    public UserOrder findUserOrderByCondition(UserOrderDto userOrderDto) {
        Assert.notNull(userOrderDto, "查询条件对象不能空");
        Wrapper<UserOrder> wrapper = new EntityWrapper<>();
        //过滤删除
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return this.baseMapper.findUserOrderByCondition(userOrderDto, wrapper);
    }

    @Override
    public Map<String, String> orderQuery(UserOrderDto userOrderDto) {
        Assert.notNull(userOrderDto.getBizOrderNo(), "订单号不存在");
        UserOrder userOrder = this.findUserOrderById(userOrderDto.getId());
        Assert.notNull(userOrder, "订单不存在");
        String payType = userOrder.getPayType();
        if (payType.equals(WXPAY)) {
            return this.wxOrderQuery(userOrder);
        } else {
            return null; //其他第三方订单查询
        }
    }

    /**
     * 微信订单查询
     *
     * @param userOrder
     * @return
     */
    private Map<String, String> wxOrderQuery(UserOrder userOrder) {
        Map<String, String> params = new HashMap<>();
        PayChannelConfigDto payChannelConfigDto = new PayChannelConfigDto();
        payChannelConfigDto.setCode(WXPAY);
        PayChannelConfig payChannelConfig = payChannelConfigServiceInterface.findPayChannelConfigByCondition(payChannelConfigDto);
        params.put("appid", payChannelConfig.getAppId());
        params.put("mch_id", payChannelConfig.getMchId());
        if (userOrder.getTransactionId() != null) {
            params.put("transaction_id", userOrder.getTransactionId());
        } else {
            params.put("out_trade_no", userOrder.getBizOrderNo());
        }
        params.put("nonce_str", WxPayKit.generateStr());
        String sign = WxPayKit.createSign(params, payChannelConfig.getWxKey(), SignType.HMACSHA256);
        params.put("sign", sign);
        String xmlResult = WxPayApi.orderQuery(false, params);

        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
        String returnCode = result.get("return_code");
        if (WxPayKit.verifyNotify(result, payChannelConfig.getWxKey(), SignType.HMACSHA256)) {
            if (!WxPayKit.codeIsOk(returnCode)) {
                if (!WxPayKit.codeIsOk(returnCode)) {
                    return result;
                }
            }
            String resultCode = result.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                return result;
            }

            String trade_state = result.get("trade_state");
            if (WxPayKit.codeIsOk(trade_state)) {
                if (userOrder.getPayStatus() != OperationConstant.TWO) {
                    userOrder.setPayStatus(OperationConstant.TWO);
                    this.updateUserOrder(userOrder);
                }
            } else {
                String trade_state_msg = null;
                switch (trade_state) {
                    case "REFUND": {
                        trade_state_msg = "转入退款";
                        break;
                    }
                    case "NOTPAY": {
                        trade_state_msg = "未支付";
                        break;
                    }
                    case "CLOSED": {
                        trade_state_msg = "已关闭";
                        break;
                    }
                    case "REVOKED": {
                        trade_state_msg = "已撤销";
                        break;
                    }
                    case "USERPAYING": {
                        trade_state_msg = "用户支付中    ";
                        break;
                    }
                    case "PAYERROR": {
                        trade_state_msg = "支付失败(其他原因，如银行返回失败)";
                        break;
                    }
                }
                result.put("trade_state_msg", trade_state_msg);
            }
            return result;
        } else {
            Map<String, String> errorResult = new HashMap<>();
            errorResult.put("return_code", "FAIL");
            errorResult.put("return_msg", result.get("return_msg"));
            return errorResult;
        }
    }

    /**
     * 生成业务订单号
     *
     * @return
     */
    protected String genBizOrderNo() {

        int hashCode = UUID.randomUUID().toString().hashCode();

        if (hashCode < 0) {//有可能是负数
            hashCode = -hashCode;
        }
//        String bizOrderNo = String.valueOf(hashCode);
//        bizOrderNo = String.format("%010d", hashCode);
        String bizOrderNo = "D" + String.format("%010d", hashCode);
        return bizOrderNo;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public UserOrder addUserOrderByImport(UserOrderDto userOrderDto) {
        UserOrder order = this.getByOldId(userOrderDto.getOldId());
        if (order != null) {
            return null;
        }
        FaceChargeProjectResidentialUserDto dto = new FaceChargeProjectResidentialUserDto();
        UserOrder userOrder = new UserOrder();
        BeanUtils.copyProperties(userOrderDto, userOrder);
        if (StringUtils.isEmpty(userOrderDto.getBizOrderNo())){
            userOrder.setBizOrderNo(genBizOrderNo());
            userOrder.setOrderType("FACE_ENABLE");
            userOrder.setShouldPayAmount(new BigDecimal(0.00));
            userOrder.setActualPayAmount(new BigDecimal(0.00));
            userOrder.setPayStatus(OperationConstant.ONE);
        }
        userOrder.setRefund(OperationConstant.ZERO);
        //通过oldUserId找用户name tel 新id
        User user = this.userFeign.getByOldId(userOrderDto.getOldUserId());
        if (null != user) {
            userOrder.setName(user.getName());
            userOrder.setTel(user.getTel());
            userOrder.setUserId(user.getId());
            dto.setUserId(user.getId());
        }
        //通过oldGoodsId找商品新id
        FaceChargeProject faceChargeProject = this.faceChargeProjectFeign.getByOldId(userOrderDto.getOldGoodsId());
        if (null != faceChargeProject) {
            userOrder.setGoodsId(faceChargeProject.getId());
            dto.setFaceChargeId(faceChargeProject.getId());
            dto.setTypeItem(faceChargeProject.getTypeItem());
        }
        //通过oldResidentialId找name 新id
        Residential residential = this.residentialFeign.getByOldId(userOrderDto.getOldResidentialId());
        if (null != residential) {
            userOrder.setResidentialId(residential.getId());
            userOrder.setResidentialName(residential.getName());
            dto.setResidentialId(residential.getId());
        }
        Unit unit = this.unitFeign.getByOldId(userOrderDto.getOldUnitId());
        if (null != unit) {
            userOrder.setUnitId(unit.getId());
            userOrder.setUnitName(unit.getName());
        }
        Room room = this.roomFeign.getByOldId(userOrderDto.getOldRoomId());
        if (null != room) {
            userOrder.setRoomId(room.getId());
            userOrder.setRoomName(room.getName());
        }
        Date today = new Date();
        dto.setCreateDate(today);
        Boolean b = this.insert(userOrder);
        ResultBean<Boolean> bean = faceChargeProjectResidentialUserFeign.addFaceChargeProjectResidentialUser(dto);
        if (b && true == bean.getData()) {
            return userOrder;
        }
        return null;
    }


    @Override
    public UserOrder getByOldId(String oldId) {
        Wrapper<UserOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("l_old_id", oldId);
        return this.selectOne(wrapper);
    }
}
