package com.neusoft.smart.pos.order.controller;

import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.order.request.*;
import com.neusoft.smart.pos.dto.order.response.*;
import com.neusoft.smart.pos.dto.order.response.GetOrderDetailsResponse;
import com.neusoft.smart.pos.dto.order.response.GetOrderPayStatusResponse;
import com.neusoft.smart.pos.dto.order.response.PostOrderResponse;
import com.neusoft.smart.pos.dto.order.response.PostRefundOrderResponse;
import com.neusoft.smart.pos.dto.payorder.request.PostCreatePayOrderRequest;
import com.neusoft.smart.pos.dto.payorder.request.PutReversePayOrderRequest;
import com.neusoft.smart.pos.dto.payorder.response.PostPayOrderResponse;
import com.neusoft.smart.pos.dto.payorder.response.PutReversePayOrderResponse;
import com.neusoft.smart.pos.dto.trade.request.GetTradeShopOrderDetailsRequest;
import com.neusoft.smart.pos.dto.trade.response.GetOrderDetailListResponse;
import com.neusoft.smart.pos.framework.bean.PaginationExtendBean;
import com.neusoft.smart.pos.framework.constants.SignatureConstants;
import com.neusoft.smart.pos.framework.dto.ResponseData;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.ConditionUtils;
import com.neusoft.smart.pos.framework.utils.DateUtils;
import com.neusoft.smart.pos.framework.utils.SignatureUtils;
import com.neusoft.smart.pos.order.constants.TradeErrorCode;
import com.neusoft.smart.pos.order.persistent.domain.OrderMaster;
import com.neusoft.smart.pos.order.service.OrderService;
import com.neusoft.smart.pos.order.service.OrderStatisticsService;
import com.neusoft.smart.pos.order.service.RefundOrderService;
import com.neusoft.smart.pos.order.utils.WXTokenUtils;
import com.neusoft.smart.pos.payment.persistent.ext.domain.ThirdPlatformRefundOrder;
import com.neusoft.smart.pos.payment.persistent.ext.domain.ThirdPlatformReverseOrder;
import com.neusoft.smart.pos.payment.service.PaymentService;
import com.neusoft.smart.pos.payment.service.RemoteCardTradeService;
import com.neusoft.smart.pos.payorder.constants.PayErrorCode;
import com.neusoft.smart.pos.payorder.persistent.domain.PayOrder;
import com.neusoft.smart.pos.payorder.persistent.domain.PayRefundOrder;
import com.neusoft.smart.pos.payorder.persistent.domain.TradeMchPayDetail;
import com.neusoft.smart.pos.payorder.persistent.domain.TradeSettlementInfo;
import com.neusoft.smart.pos.payorder.repository.PayChannelRepository;
import com.neusoft.smart.pos.payorder.repository.TradeMchPayDetailRepository;
import com.neusoft.smart.pos.payorder.service.PayOrderService;
import com.neusoft.smart.pos.payorder.service.PayRefundOrderService;
import com.neusoft.smart.pos.payorder.service.TradeSettlementQueryService;
import com.neusoft.smart.pos.utils.PosDeviceRedisUtils;
import com.neusoft.smart.pos.utils.RequestHeaderUtil;
import com.neusoft.smart.pos.utils.SequenceUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

@Api(value = "订单管理使用接口", description = "订单管理使用接口")
@RestController
@RequestMapping(path = "/ordermanager")
@Validated
public class OrderController {

    @Autowired
    private OrderService orderService;// = ServiceFactory.getOrderServiceInstance(null,null);

    @Autowired
    private RefundOrderService refundOrderService;

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private PayRefundOrderService payRefundOrderService;

    @Autowired
    private TradeSettlementQueryService tradeSettlementQueryService;

    @Autowired
    private PaymentService paymentService;

    @Resource
    private RemoteCardTradeService remoteCardTradeService;

    @Autowired
    private OrderStatisticsService orderStatisticsService;

    @Autowired
    private TradeMchPayDetailRepository tradeMchPayDetailRepository;

    @Autowired
    private PayChannelRepository payChannelRepository;

    @ApiOperation(value = "订单生成使用接口", notes = "订单生成使用方法")
    @PostMapping("/createOrder")
    public ResponseData<PostOrderResponse> createOrder(@RequestBody PostCreateOrderRequest createOrderRequest) {

        //根据设备SN校正orgId和shopId
        if(createOrderRequest.getSerialNo() != null && !createOrderRequest.getSerialNo().isEmpty()) {
            //1.查询订单信息，并进行校验
            val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(createOrderRequest.getSerialNo());
            if (null == deviceInfo) {
                throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
            }

            createOrderRequest.setOrgId(deviceInfo.getOrganizationId());
            createOrderRequest.setShopId(deviceInfo.getStoreId());
        }

        //如果订单类型参数为空，默认为普通订单
        if(createOrderRequest.getOrderType() == null || createOrderRequest.getOrderType().isEmpty()){
            createOrderRequest.setOrderType(DictionaryConstant.ORDER_TYPE_ZC.getCode());
        }

        //序列号规则集团ID+门店ID+订单类型
        createOrderRequest.setSeqNo(SequenceUtils.getOrderSequenceNoForDay(createOrderRequest.getOrgId() + "_" + createOrderRequest.getShopId() + "_" + createOrderRequest.getOrderType()));


        return new ResponseData<>(orderService.createOrder(createOrderRequest));
    }

    //doPay
    @ApiOperation(value = "创建支付订单接口", notes = "创建支付订单接口")
    @PostMapping("/createPayOrder")
    public ResponseData<PostPayOrderResponse> createPayOrder(@RequestBody PostCreatePayOrderRequest createPayOrderRequest) {
        PayOrder resultPayOrder = createPayOrderInfo(createPayOrderRequest);
        val payOrderResponse = new com.neusoft.smart.pos.dto.payorder.response.PostPayOrderResponse();
        BeanUtils.copyProperties(resultPayOrder, payOrderResponse);
        orderService.computeOrderStatus(createPayOrderRequest.getOrderNumber());
        return new ResponseData<>(payOrderResponse);
    }

    private PayOrder createPayOrderInfo(PostCreatePayOrderRequest createPayOrderRequest){
        PayOrder payOrder = new PayOrder();
        BeanUtils.copyProperties(createPayOrderRequest, payOrder);
        payOrder.setmOrderNumber(createPayOrderRequest.getOrderNumber());
        val orderMaster = orderService.getOrderMasterByOrderNumber(createPayOrderRequest.getOrderNumber());
        //3.查询商户结算及聚合支付平台商户信息
        TradeSettlementInfo tradeSettlementInfo = tradeSettlementQueryService.queryTradeSettlementInfo(orderMaster.getOrgId(), orderMaster.getShopId());
        if (null == tradeSettlementInfo) {
            throw new BusinessCommonException(PayErrorCode.TRADE_SETTLEMENT_INFO_EMPTY);
        }

        //4.查询商户是否开通此支付方式渠道
        tradeSettlementQueryService.verifyShopPayChannelByPayType(orderMaster.getOrgId(), orderMaster.getShopId(), createPayOrderRequest.getPayType());

        //5.根据支付方式查询支付信息
        val payTypeDict = tradeSettlementQueryService.queryEnablePayTypeDict(createPayOrderRequest.getPayType());

        //7.获得openId
        val tradeMchPayChannel = payChannelRepository.queryShopPayChannelByPayType(orderMaster.getOrgId(),orderMaster.getShopId(),createPayOrderRequest.getPayType());
        String openIdTemp;
        String openId;
        String openIdCode;
        net.sf.json.JSONObject payInfoJsonObject  = net.sf.json.JSONObject.fromObject(payOrder.getRequestDetailInfo());
        try {
            openId = payInfoJsonObject.getString("openId");
        } catch (Exception e) {
            openId = null;
        }
        try {
            openIdCode = payInfoJsonObject.getString("openIdCode");
        } catch (Exception e) {
            openIdCode = null;
        }
        if (!StringUtils.isEmpty(openIdCode) && StringUtils.isEmpty(openId) && tradeMchPayChannel != null) {
            openIdTemp = WXTokenUtils.getOpenId(tradeMchPayChannel.getAppid(), tradeMchPayChannel.getAppSecretKey(), openIdCode);
        } else {
            openIdTemp = openId;
        }

        payOrder.setMcode(tradeSettlementInfo.getMcode());
        payOrder.setDescription("商品支付订单");
        payOrder.setPayTypeName(DictionaryConstant.getEnumByCode(DictionaryConstant.PAY_TYPE.getCode(), createPayOrderRequest.getPayType()).getValue());
        payOrder.setNotifyUrl(payTypeDict.getNotifyUrl());
        payOrder.setTimeExpire(DateUtils.format(orderMaster.getTimeExpire()));
//        payOrder.setPayIp(ip); // TODO 微信公众号支付需要ip，需接口传入
        payOrder.setOpenId(openIdTemp);
        payOrder.setTradeType(DictionaryConstant.WX_TRADE_TYPE_NATIVE.getCode()); // TODO 微信公众号支付用WX_TRADE_TYPE_JSAPI，从接口区分
        payOrder.setDeviceId(orderMaster.getSerialNo());
        payOrder.setDeviceName(orderMaster.getDeviceName());
        TradeMchPayDetail tradeMchPayDetail = tradeMchPayDetailRepository.queryOrderByOrderNumber(orderMaster.getOrgId(), orderMaster.getShopId(), createPayOrderRequest.getPayType());
        if (null != tradeMchPayDetail) {
            payOrder.setStoreId(tradeMchPayDetail.getStoreId());
            payOrder.setPid(tradeMchPayDetail.getPid());
        }
        if(DictionaryConstant.ORDER_TYPE_HYCZ.getCode().equals(orderMaster.getOrderType())){
            if(payOrder.getRequestDetailInfo()!=null && !"".equals(payOrder.getRequestDetailInfo())) {
                try {
                    payOrder.setCardNum(payInfoJsonObject.getString("cardNum"));
                } catch (Exception e) {
                    throw new BusinessCommonException(TradeErrorCode.MEMBER_CARD_IS_EMPTY);
                }
            }else{
                throw new BusinessCommonException(TradeErrorCode.MEMBER_CARD_IS_EMPTY);
            }
        }

        PayOrder resultPayOrder = payOrderService.createPayOrder(payOrder);
        return resultPayOrder;
    }

    @ApiOperation(value = "创建支付订单接口", notes = "创建支付订单接口")
    @PostMapping("/postCouponsAndDiscountPayOrder")
    public ResponseData<PostPayOrderResponse> postCouponsAndDiscountPayOrder(@RequestBody CouponsAndDiscountRequest couponsAndDiscountRequest) {
        val payOrderResponse = new com.neusoft.smart.pos.dto.payorder.response.PostPayOrderResponse();
        Date payTime = new Date();
        long discount = couponsAndDiscountRequest.getDiscountAmount();
        if (discount > 0) {
            PayOrder resultDiscountPayOrder = createSimplePayOrder(couponsAndDiscountRequest.getOrderNumber(), DictionaryConstant.PAY_TYPE_DISCOUNT.getCode(), discount, null);
            boolean bResult = payOrderService.paySuccess(resultDiscountPayOrder.getTradeId(), resultDiscountPayOrder.getmOrderNumber(),payTime);
            if (!bResult) {
                //
            }
        }

        //富茂优惠券支付参数(组JSON)：tenant_id，merchant_id，order_operator_id，
        // order_amount，mem_phone_number，mem_id，business_type，order_left_amount，coupon_list
        long couponsAmount = couponsAndDiscountRequest.getCouponsAmount();
        if (couponsAmount > 0) {
            PayOrder resultPayOrder = createSimplePayOrder(couponsAndDiscountRequest.getOrderNumber(), DictionaryConstant.PAY_TYPE_FM_COUPON.getCode(), couponsAmount,couponsAndDiscountRequest.getCouponsRequestString());
            String result = paymentService.createPayOrder(resultPayOrder);
            //boolean bResult = payOrderService.paySuccess(resultPayOrder.getTradeId(), resultPayOrder.getmOrderNumber(), payTime);
            if (DictionaryConstant.PAY_STATUS_YFK.getCode().equals(resultPayOrder.getPayStatus())) {
                resultPayOrder.setPayTime(payTime);
            }
            payOrderService.updatePayOrder(resultPayOrder);
            BeanUtils.copyProperties(resultPayOrder, payOrderResponse);
        }
        if(couponsAndDiscountRequest.getBuyerId()!=null && !"".equals(couponsAndDiscountRequest.getBuyerId())){
            OrderMaster updateOrder = new OrderMaster();
            updateOrder.setOrderNumber(couponsAndDiscountRequest.getOrderNumber());
            updateOrder.setBuyerId(couponsAndDiscountRequest.getBuyerId());
            orderService.updateOrderInfo(updateOrder);
        }

        if (discount > 0 || couponsAmount > 0) {
            orderService.computeOrderStatus(couponsAndDiscountRequest.getOrderNumber());
        }
        return new ResponseData<>(payOrderResponse);
    }

    private PayOrder createSimplePayOrder(String orderNumber, String payType, long couponsAmount,String requestDetailInfo) {
        PostCreatePayOrderRequest createPayOrderRequest = new PostCreatePayOrderRequest();
        createPayOrderRequest.setPayType(payType);
        createPayOrderRequest.setOrderNumber(orderNumber);
        createPayOrderRequest.setPayAmount(couponsAmount);
        createPayOrderRequest.setRequestDetailInfo(requestDetailInfo);
        PayOrder resultPayOrder = createPayOrderInfo(createPayOrderRequest);
        return resultPayOrder;
    }

    //doPay
    @ApiOperation(value = "预支付返回接口", notes = "预支付返回接口")
    @PostMapping("/doPay")
    public ResponseData<PostDoPayOrderResponse> doPay(@RequestBody PostDoPayOrderRequest doPayOrderRequest) {
        PayOrder payOrder = payOrderService.getPayOrder(doPayOrderRequest.getTradeId());
        // 处理requestJsonString
        String newParams = doPayOrderRequest.getPrePayParameter();
        if(newParams != null && !newParams.isEmpty()) {
            String oldParams = payOrder.getRequestDetailInfo();
            JSONObject paramsJson;
            if(oldParams != null && !oldParams.isEmpty()) {
                try {
                    paramsJson = new JSONObject(oldParams);
                } catch (JSONException e) {
                    paramsJson = new JSONObject();
                }
            } else {
                paramsJson = new JSONObject();
            }

            JSONObject paramsNewJson;
            try {
                paramsNewJson = new JSONObject(newParams);
            } catch (JSONException e) {
                paramsNewJson = new JSONObject();
            }
            for(String key:paramsNewJson.keySet()) {
                paramsJson.put(key, paramsNewJson.get(key));
            }
            payOrder.setRequestDetailInfo(paramsJson.toString());
        }

        payOrder.setDeviceId(doPayOrderRequest.getDeviceSN());
        String prePayResult = paymentService.createPayOrder(payOrder);
        if (prePayResult != null) {
            payOrderService.updatePayOrder(payOrder);
        } else {
            throw new BusinessCommonException(PayErrorCode.TRADE_SETTLEMENT_INFO_EMPTY);
        }
        val postDoPayOrderResponse = new com.neusoft.smart.pos.dto.order.response.PostDoPayOrderResponse();
        postDoPayOrderResponse.setPrePayResult(prePayResult);
        postDoPayOrderResponse.setPayStatus(payOrder.getPayStatus());
        postDoPayOrderResponse.setPaidTime(DateUtils.format(payOrder.getPayTime(),DateUtils.FORMAT_LONG));
        orderService.computeOrderStatus(payOrder.getmOrderNumber());
        return new ResponseData<>(postDoPayOrderResponse);
    }

    @ApiOperation(value = "更新订单支付结果接口", notes = "更新订单支付结果接口")
    @PutMapping("/updatePayResult")
    public ResponseData<UpdateOrderPayResultResponse> updatePayResult(@Valid @RequestBody SetOrderPayResultRequest setPayResultRequest, BindingResult bindingResult) {
        PayOrder payOrder = payOrderService.getPayOrder(setPayResultRequest.getTradeId());
        boolean bResult = false;
        Date payTime = new Date();
        if("1".equals(setPayResultRequest.getPayResult())){
            bResult = payOrderService.paySuccess(payOrder.getTradeId(), payOrder.getmOrderNumber(), payTime,
                    setPayResultRequest.getTraceNo(), setPayResultRequest.getBatchNo(), setPayResultRequest.getRefNo(),
                    setPayResultRequest.getTransDate(), setPayResultRequest.getResponseDetailInfo());
        }else {
            bResult = payOrderService.updatePayOrderStatus(setPayResultRequest.getTradeId(),DictionaryConstant.PAY_STATUS_YQX.getCode());
        }

        val response = new com.neusoft.smart.pos.dto.order.response.UpdateOrderPayResultResponse(bResult);
        response.setPayTime(DateUtils.formatDate(payTime,DateUtils.FORMAT_LONG));
        orderService.computeOrderStatus(payOrder.getmOrderNumber());
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "创建并支付支付订单接口", notes = "创建支付订单接口")
    @PostMapping("/createAndPayPayOrder")
    public ResponseData<PostPayOrderResponse> createAndPayPayOrder(@RequestBody PostCreatePayOrderRequest createPayOrderRequest) {
        PayOrder resultPayOrder = createPayOrderInfo(createPayOrderRequest);
        Date payTime = new Date();
        boolean bResult = payOrderService.paySuccess(resultPayOrder.getTradeId(), resultPayOrder.getmOrderNumber(),payTime);
        if (bResult) {
            resultPayOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
            resultPayOrder.setPayTime(payTime);
        }
        val response = new com.neusoft.smart.pos.dto.payorder.response.PostPayOrderResponse();
        BeanUtils.copyProperties(resultPayOrder, response);
        response.setPayTime(DateUtils.formatDate(payTime,DateUtils.FORMAT_LONG));
        orderService.computeOrderStatus(createPayOrderRequest.getOrderNumber());
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "支付单撤销接口", notes = "支付单撤销接口")
    @PutMapping("/reversePayOrder")
    public ResponseData<PutReversePayOrderResponse> reversePayOrder(@RequestBody PutReversePayOrderRequest putReversePayOrderRequest) {
        PayOrder payOrder = payOrderService.getPayOrder(putReversePayOrderRequest.getTradeId());
        ThirdPlatformReverseOrder thirdPlatformReverseOrder = paymentService.reversePayOrder(payOrder);

        PutReversePayOrderResponse putReversePayOrderResponse = new PutReversePayOrderResponse();
        if(null != thirdPlatformReverseOrder && thirdPlatformReverseOrder.getReverseStatus().equals("1")){
            throw new BusinessCommonException(TradeErrorCode.PAY_PLATFORM_REVERSE_ORDER_ERROR);
        }
        putReversePayOrderResponse.setIsSuccess(true);
        //更新支付单状态
        payOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YQX.getCode());//状态为关闭
        payOrder.setUpdatedAt(new Date());
        payOrderService.updatePayOrder(payOrder);
        //订单状态更新
        orderService.computeOrderStatus(payOrder.getmOrderNumber());
        return new ResponseData<>(putReversePayOrderResponse);
    }

    @ApiOperation(value = "查询聚合支付平台订单支付状态接口", notes = "根据订单编号查询第三方平台支付状态方法")
    @GetMapping("/queryPayOrderStatusByThirdPlatform")
    public ResponseData<GetOrderPayStatusResponse> queryPayOrderStatusByThirdPlatform(@RequestParam(value="tradeId",defaultValue = "") String tradeId ,@RequestParam(value="orderNumber",defaultValue = "") String orderNumber , @RequestParam(value="serialNo",defaultValue = "") String serialNo) {
        val response = payOrderService.queryOrderPayStatusByThirdPlatform(serialNo , tradeId);
        boolean bResult = false;
        if(DictionaryConstant.PAY_STATUS_YFK.getCode().equals(response.getPayStatus())){
            bResult = payOrderService.paySuccess(tradeId, orderNumber, DateUtils.parse(response.getPaidTime()));
        }else if(DictionaryConstant.PAY_STATUS_YQX.getCode().equals(response.getPayStatus())){
            bResult = payOrderService.updatePayOrderStatus(tradeId, DictionaryConstant.PAY_STATUS_YQX.getCode());
        }

        if(bResult) {
            orderService.computeOrderStatus(orderNumber);
        }else{
            throw new BusinessCommonException(TradeErrorCode.PAY_ORDER_UPDATE_ERROR);
        }
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "订单取消使用接口", notes = "根据订单编号设置订单状态为已取消的方法")
    @PutMapping("/cancelOrder")
    public ResponseData<PutCancelOrderResponse> cancelOrder(@RequestBody PutCancelOrderRequest cancleOrderRequest) {
        //根据设备SN校正orgId和shopId
        if(cancleOrderRequest.getSerialNo() != null && !cancleOrderRequest.getSerialNo().isEmpty()) {
            //1.查询订单信息，并进行校验
            val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(cancleOrderRequest.getSerialNo());
            if (null == deviceInfo) {
                throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
            }

            cancleOrderRequest.setOrgId(deviceInfo.getOrganizationId());
            cancleOrderRequest.setShopId(deviceInfo.getStoreId());
        }
        return new ResponseData<>(orderService.cancelOrder(cancleOrderRequest));
    }

    @ApiOperation(value = "设置订单状态使用接口", notes = "设置订单状态使用接口")
    @PutMapping("/setOrderStatus")
    public ResponseData<PutSetOrderStatusResponse> setOrderStatus(@RequestBody PutSetOrderStatusRequest setOrderStatusRequest) {
        //根据设备SN校正orgId和shopId
        if(setOrderStatusRequest.getSerialNo() != null && !setOrderStatusRequest.getSerialNo().isEmpty()) {
            //1.查询订单信息，并进行校验
            val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(setOrderStatusRequest.getSerialNo());
            if (null == deviceInfo) {
                throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
            }

            setOrderStatusRequest.setOrgId(deviceInfo.getOrganizationId());
            setOrderStatusRequest.setShopId(deviceInfo.getStoreId());
        }
        return new ResponseData<>(orderService.setOrderStatus(setOrderStatusRequest));
    }
    @ApiOperation(value = "订单信息查询接口", notes = "根据订单编号查询订单信息方法")
    @GetMapping("/getOrderInfo")
    public ResponseData<GetAllOrderInfoResponse> getOrderInfo(@RequestParam(value="orderNumber",defaultValue = "") String orderNumber) {
        //orderService.computeOrderStatus(orderNumber);
        return new ResponseData<>(orderService.getOrderInfoByOrderNumber(orderNumber));
    }

    @ApiOperation(value = "订单商品信息列表查询接口", notes = "订单信息商品信息列表查询方法")
    @GetMapping("/getOrderGoodsList")
    public ResponseData<GetOrderDetailsResponse> getOrderGoodsList(@RequestParam(value="orderNumber",defaultValue = "") String orderNumber) {
        return new ResponseData<>(orderService.getOrderGoodsListByOrderNumber(orderNumber));
    }

    @ApiOperation(value = "退款订单生成使用接口", notes = "退款订单生成使用方法")
    @PostMapping("/createRefundOrder")
    public ResponseData<PostRefundOrderResponse> createRefundOrder(@RequestBody PostCreateRefundOrderRequest createRefundOrderRequest) {
        return new ResponseData<>(refundOrderService.createRefundOrder(createRefundOrderRequest));
    }

    @ApiOperation(value = "更新退款结果接口", notes = "更新退款结果接口")
    @PutMapping("/updateRefundResult")
    public ResponseData<UpdateRefundResultResponse> updateRefundResult(@Valid @RequestBody SetRefundResultRequest setRefundResultRequest, BindingResult bindingResult) {
        PayOrder payOrder = payOrderService.getPayOrder(setRefundResultRequest.getPayOrderId());
        PayRefundOrder payRefundOrder = payRefundOrderService.getPayRefundOrder(setRefundResultRequest.getPayRefundOrderId());
        ThirdPlatformRefundOrder prePayResult = paymentService.refundPayOrder(payOrder, setRefundResultRequest.getPayRefundOrderId(), payRefundOrder.getRefundedAmount());
        val updateRefundResultResponse = new com.neusoft.smart.pos.dto.order.response.UpdateRefundResultResponse();
        if (prePayResult != null) {
            if ("2".equals(prePayResult.getRefundStatus())) {
                PayRefundOrder updatePayRefundOrder = new PayRefundOrder();
                updatePayRefundOrder.setOuterOrderNumber(payRefundOrder.getOuterOrderNumber());
                updatePayRefundOrder.setRefundedTime(new Date());
                updatePayRefundOrder.setRefundStatus(DictionaryConstant.PAY_REFUND_STATUS__YTK.getCode());
                updatePayRefundOrder.setThirdRefundNumber(prePayResult.getThirdRefundNumber());
                payRefundOrderService.updatePayRefundOrder(updatePayRefundOrder);
                updateRefundResultResponse.setIsSuccess(true);
                updateRefundResultResponse.setRefundTime(DateUtils.format(updatePayRefundOrder.getRefundedTime(), DateUtils.FORMAT_LONG));
            } else {
                updateRefundResultResponse.setIsSuccess(false);
                payRefundOrderService.updatePayRefundOrderStatus(payRefundOrder.getOuterOrderNumber(), DictionaryConstant.PAY_REFUND_STATUS__YQX.getCode());
            }
        } else {
            throw new BusinessCommonException(PayErrorCode.TRADE_SETTLEMENT_INFO_EMPTY);
        }
        payOrderService.computePayOrderStatus(payOrder.getTradeId());
        refundOrderService.computeRefundOrderStatus(payRefundOrder.getRefundNumber());
        orderService.computeOrderStatus(payOrder.getmOrderNumber());
        return new ResponseData<>(updateRefundResultResponse);
    }


    @ApiOperation(value = "招行充值支付创建订单接口", notes = "招行充值支付创建订单接口")
    @PostMapping("/neusofCardRecharge")
    public ResponseData<NeusofMemberRechargeResponse> neusofCardRecharge(@RequestBody NeusoftMemberRechargeRequest neusofMemberRechargeRequest) {
        Map signMapData = getSignMapData(neusofMemberRechargeRequest);
        if (!SignatureUtils.isSignatureValid(signMapData, SignatureConstants.CMB_SIGN_KTY)) {
            throw new BusinessCommonException(TradeErrorCode.TRADE_MCH_SIGN_VALIDATE_ERROR);
        }

//        val payOrder = payOrderService.getPayOrderByOuterOrderNumber(neusofMemberRechargeRequest.getTransNo());
//
//        if (payOrder != null) {
//            throw new BusinessCommonException(TradeErrorCode.PAY_ORDER_INFO_NOT_EXIST);
//        }

        val response = new com.neusoft.smart.pos.dto.order.response.NeusofMemberRechargeResponse();

        PostCreateOrderRequest createOrderRequest = new PostCreateOrderRequest();

        if(neusofMemberRechargeRequest.getMcode() != null && !neusofMemberRechargeRequest.getMcode().isEmpty()) {
            //1.查询订单信息，并进行校验
            val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(neusofMemberRechargeRequest.getMcode());
            if (null == deviceInfo) {
                throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
            }

            createOrderRequest.setOrgId(deviceInfo.getOrganizationId());
            createOrderRequest.setShopId(deviceInfo.getStoreId());
        }else{
            throw new BusinessCommonException(TradeErrorCode.POS_SN_EMPTY);
        }

        createOrderRequest.setSerialNo(neusofMemberRechargeRequest.getMcode());
        createOrderRequest.setOrderAmount(neusofMemberRechargeRequest.getAmount());
        createOrderRequest.setOrderType(DictionaryConstant.ORDER_TYPE_HYCZ.getCode());
        createOrderRequest.setBuyerId(neusofMemberRechargeRequest.getMemberCardNo());

        val orderResponse = orderService.createOrder(createOrderRequest);

        PayOrder resultPayOrder = createSimplePayOrder(orderResponse.getOrderNumber(), DictionaryConstant.PAY_TYPE_CZ_ONLINE.getCode(), orderResponse.getOrderAmount(), "{cardNum:"+ neusofMemberRechargeRequest.getMemberCardNo() + "}");
        resultPayOrder.setPayTime(DateUtils.parse(neusofMemberRechargeRequest.getTime()));
        resultPayOrder.setOuterOrderNumber(neusofMemberRechargeRequest.getTransNo());
        resultPayOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
        resultPayOrder.setMcode(neusofMemberRechargeRequest.getMcode());

        JSONObject paramsNewJson = new JSONObject();

        paramsNewJson.put("cardNum", neusofMemberRechargeRequest.getMemberCardNo());
        resultPayOrder.setRequestDetailInfo(paramsNewJson.toString());
        payOrderService.updatePayOrder(resultPayOrder);
        orderService.computeOrderStatus(orderResponse.getOrderNumber());

        val result = remoteCardTradeService.balance(neusofMemberRechargeRequest.getMemberCardNo(),null,null);
        response.setBalance(result.getResult());
        response.setOrderNo(resultPayOrder.getTradeId());
        return new ResponseData<>(response);
    }

    private Map<String, String> getSignMapData(NeusoftMemberRechargeRequest neusofMemberRechargeRequest) {
        Map<String, String> data = new HashMap();
        data.put("mcode",neusofMemberRechargeRequest.getMcode());
        data.put("memberCardNo",neusofMemberRechargeRequest.getMemberCardNo());
        data.put("time",neusofMemberRechargeRequest.getTime());
        data.put("transNo",neusofMemberRechargeRequest.getTransNo());
        data.put("amount","" + neusofMemberRechargeRequest.getAmount());
        data.put("nonce",neusofMemberRechargeRequest.getNonce());
        data.put("timestamp",neusofMemberRechargeRequest.getTimestamp());
        data.put("sign",neusofMemberRechargeRequest.getSign());
        return data;
    }

    @ApiOperation(value = "充值订单落地状态查询", notes = "充值订单落地状态查询")
    @GetMapping("/getOrderStatusbyThirdTrans")
    public ResponseData<ThirdTransGetOrderStatusResponse> getOrderStatusbyThirdTrans(@RequestParam(value = "mcode", defaultValue = "", required = false) String mcode,
                                                                                     @RequestParam(value = "sign", required = false) String sign,
                                                                                     @RequestParam(value = "transNo", defaultValue = "", required = false) String transNo,
                                                                                     @RequestParam(value = "nonce", defaultValue = "", required = false) String nonce,
                                                                                     @RequestParam(value = "timestamp", defaultValue = "", required = false) String timestamp) {
        Map signMapData = getSignMapData(mcode, transNo, nonce, timestamp, sign);
        if (!SignatureUtils.isSignatureValid(signMapData, SignatureConstants.CMB_SIGN_KTY)) {
            throw new BusinessCommonException(TradeErrorCode.TRADE_MCH_SIGN_VALIDATE_ERROR);
        }
        val response = new ThirdTransGetOrderStatusResponse();
        val payOrder = payOrderService.getPayOrderByOuterOrderNumber(transNo);

        if (payOrder == null) {
            //throw new BusinessCommonException(TradeErrorCode.PAY_ORDER_INFO_NOT_EXIST);
            response.setOrderNo(" ");
            response.setTransNo(transNo);
            response.setOrderCode("01");
            response.setOrderMessage("订单不存在");
        }else {
            response.setOrderNo(payOrder.getTradeId());
            response.setTransNo(transNo);
            if (DictionaryConstant.PAY_STATUS_YFK.getCode().equals(payOrder.getPayStatus())) {
                response.setOrderCode("00");
                response.setOrderMessage("支付成功");
            } else {
                response.setOrderCode("01");
                response.setOrderMessage("支付失败");
            }
        }
        return new ResponseData<>(response);
    }

    @ApiOperation(value = "查询订单列表", notes = "查询订单列表")
    @GetMapping("/getOrderList")
    public ResponseData<GetOrderDetailListResponse> getOrderList(
            @RequestParam(value = "username",    required = false)                        String username,
            @RequestParam(value = "orderStatus", required = false)                        String orderStatus,
            @RequestParam(value = "orderSubType",required = false)                        String orderSubType,
            @RequestParam(value = "orgId",       required = false)                        String orgId,
            @RequestParam(value = "shopId",      required = false)                        String shopId,
            @RequestParam(value = "startTime",   required = false)                        String startTime,
            @RequestParam(value = "endTime",     required = false)                        String endTime,
            @RequestParam(value = "offset",      defaultValue = "0", required = false)    Integer offset,
            @RequestParam(value = "limit",       defaultValue = "20", required = false)   Integer limit,
            @RequestParam(value = "isPage",      defaultValue = "true", required = false) String isPage) {
        StringBuilder tmpUserName = new StringBuilder();
        ConditionUtils.setWithCondition(username, StringUtils::isNotEmpty, tmpUserName::append);
        ConditionUtils.emptyAllStrings(val -> {
            tmpUserName.setLength(0);
            ConditionUtils.setWithCondition(RequestHeaderUtil.getUsername(), StringUtils::isNotEmpty, tmpUserName::append);
            if(tmpUserName.length() == 0) {
                throw new BusinessCommonException(TradeErrorCode.TRADE_QUERY_CONDITION_EMPTY);
            }
        }, tmpUserName.toString(), orgId, shopId);
        ConditionUtils.vaildInteger(orgId, TradeErrorCode.ORG_ID_EMPTY);
        ConditionUtils.vaildInteger(shopId, TradeErrorCode.SHOP_ID_EMPTY);


        val request = new GetTradeShopOrderDetailsRequest();
        ConditionUtils.setWithCondition(tmpUserName.toString(),    StringUtils::isNotEmpty,      request::setCreatedBy);
        ConditionUtils.setWithCondition(orgId,       ConditionUtils::vaildInteger, v -> request.setOrgId(Integer.valueOf(v)));
        ConditionUtils.setWithCondition(shopId,      ConditionUtils::vaildInteger, v -> request.setShopIds(Collections.singletonList(Integer.valueOf(v))));
        ConditionUtils.setWithCondition(orderStatus, StringUtils::isNotEmpty,      request::setOrderStatus);
        ConditionUtils.setWithCondition(orderSubType, StringUtils::isNotEmpty,      request::setOrderSubType);
        ConditionUtils.setWithCondition(startTime,   StringUtils::isNotEmpty,      request::setStartTime,
                v -> request.setStartTime(DateUtils.format(new Date(0L), DateUtils.FORMAT_SHORT)));
        ConditionUtils.setWithCondition(endTime,     StringUtils::isNotEmpty,      request::setEndTime,
                v -> request.setEndTime(DateUtils.format(new Date(), DateUtils.FORMAT_SHORT)));
        request.setOffset(offset);
        request.setLimit(limit);

        ConditionUtils.setWithCondition(isPage,      ConditionUtils::vaildBoolean, v -> {request.setIsPage(Boolean.valueOf(v));},
                v -> request.setIsPage(Boolean.TRUE));

        //按开始及结束时间查询
        request.setTimeMode("1");
        request.setDeviceStatus(null);

        val shopOrderDetails = orderStatisticsService.queryShopOrderDetails(request);
        val shopOrderList = shopOrderDetails.getPaginationExtendBean().getRows();

        GetOrderDetailListResponse response = new GetOrderDetailListResponse();
        BeanUtils.copyProperties(shopOrderDetails, response);

        val orderExtendBean = new PaginationExtendBean<GetOrderDetailListResponse.OrderDetail>();
        orderExtendBean.setTotal(shopOrderDetails.getPaginationExtendBean().getTotal());
        orderExtendBean.setRows(new ArrayList<>());
        shopOrderList.forEach(shopOrderDetail -> {
            val detail = new GetOrderDetailListResponse.OrderDetail();
            BeanUtils.copyProperties(shopOrderDetail, detail);
            detail.setCreatedBy(shopOrderDetail.getCustomerName());
            orderExtendBean.getRows().add(detail);
        });

        response.setPaginationExtendBean(orderExtendBean);

        return new ResponseData<>(response);
    }


    @ApiOperation(value = "更新订单状态", notes = "更新订单状态")
    @PutMapping("/updateOrderStatus")
    public ResponseData<?> updateOrderStatus(@Valid @RequestBody PutUpdateOrderStatusRequest request) {
        if(request.getNewStatus() < 10 || request.getNewStatus() > 16) {
            throw new BusinessCommonException("", "newStatus只允许为10~16之间的状态");
        }
        orderService.setOrderStatus(request.getOrderNumber(), request.getOldStatus().toString(), request.getNewStatus().toString());
        return new ResponseData<>();
    }

    @ApiOperation(value = "订单试算接口", notes = "订单试算方法")
    @PostMapping("/doOrderTrial")
    public ResponseData<PostCreateOrderRequest> doOrderTrial(@RequestBody PostCreateOrderRequest createOrderRequest) {
        //根据设备SN校正orgId和shopId
        if(createOrderRequest.getSerialNo() != null && !createOrderRequest.getSerialNo().isEmpty()) {
            //1.查询订单信息，并进行校验
            val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(createOrderRequest.getSerialNo());
            if (null == deviceInfo) {
                throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
            }

            createOrderRequest.setOrgId(deviceInfo.getOrganizationId());
            createOrderRequest.setShopId(deviceInfo.getStoreId());
        }

        //如果订单类型参数为空，默认为普通订单
        if(createOrderRequest.getOrderType() == null || createOrderRequest.getOrderType().isEmpty()){
            createOrderRequest.setOrderType(DictionaryConstant.ORDER_TYPE_ZC.getCode());
        }

        return new ResponseData<>(orderService.doOrderTrial(createOrderRequest));
    }

    private Map getSignMapData(String mcode, String transNo, String nonce, String timestamp, String sign) {
        Map<String, String> data = new HashMap();
        data.put("mcode",mcode);
        data.put("transNo",transNo);
        data.put("nonce",nonce);
        data.put("timestamp",timestamp);
        data.put("sign",sign);
        return data;
    }
}
