package com.cweb.controller.pay;

import com.alibaba.fastjson.JSONObject;
import com.cweb.config.WxMsgConfig;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.pay.util.XmlUtil;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.security.AESEncodeUtil;
import com.hai.common.utils.DateUtil;
import com.hai.common.utils.IDGenerator;
import com.hai.common.utils.ResponseMsgUtil;
import com.hai.common.utils.WxUtils;
import com.hai.config.CommonSysConst;
import com.hai.config.HuiLianTongUnionCardConfig;
import com.hai.config.UnionPayConfig;
import com.hai.config.WxOrderConfig;
import com.hai.dao.HighGasOrderRefundMapper;
import com.hai.entity.*;
import com.hai.enum_type.GoodsType;
import com.hai.enum_type.PayType;
import com.hai.enum_type.RechargePayType;
import com.hai.model.OrderRefundModel;
import com.hai.model.ResponseData;
import com.hai.service.*;
import com.hai.service.pay.impl.GoodsOrderServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Controller
@RequestMapping(value = "/czOrder")
@Api(value = "充值回调")
public class CzOrderController {

    private static Logger log = LoggerFactory.getLogger(TuanYouController.class);

    @Resource
    private HighGasOrderRefundMapper highGasOrderRefundMapper;

    @Resource
    private OutRechargeOrderService outRechargeOrderService;

    @Resource
    private GoodsOrderServiceImpl goodsOrderService;

    @Resource
    private HighUserService highUserService;

    @Resource
    private HighDiscountUserRelService highDiscountUserRelService;

    @Resource
    private HighDiscountAgentCodeService highDiscountAgentCodeService;

    @Resource
    private OutRechargeOrderRecordService rechargeOrderRecordService;

    @RequestMapping(value = "/rechargeCallback", method = RequestMethod.POST)
    @ApiOperation(value = "话费充值回调")
    @ResponseBody
    public void rechargeCallback(@RequestBody String reqBodyStr, HttpServletRequest request, HttpServletResponse response) {
        try {


            JSONObject dataObject = JSONObject.parseObject(reqBodyStr, JSONObject.class);

            HighGasOrderRefund highGasOrderRefund = new HighGasOrderRefund();
            highGasOrderRefund.setCreateTime(new Date());
            highGasOrderRefund.setReturnContent(String.valueOf(dataObject));

            highGasOrderRefundMapper.insert(highGasOrderRefund);

            if (dataObject.getInteger("status") == 3) {
                OutRechargeOrder order;
                OutRechargeOrderRecord rechargeOrderRecord = rechargeOrderRecordService.findByOrderNo(dataObject.getString("out_order_id"));
                if (rechargeOrderRecord == null) {
                    // 查询订单
                    order = outRechargeOrderService.findByOrderNo(dataObject.getString("out_order_id"));
                    order.setStatus(3);
                    order.setFinishTime(new Date());
                    outRechargeOrderService.updateOrder(order);
                } else {
                    // 查询订单
                    order = outRechargeOrderService.findByOrderId(rechargeOrderRecord.getRechargeOrderId());
                    order.setStatus(3);
                    order.setFinishTime(new Date());
                    outRechargeOrderService.updateOrder(order);
                }

                new Thread(() -> {
                    HighUser highUser = highUserService.findByUserId(order.getUserId());
                    WxMsgConfig.rechargedSuccess(
                             order.getRechargeName() + "充值成功",
                            String.valueOf(order.getPayRealPrice()),
                            order.getOrderNo(),
                            order.getFinishTime(),
                            RechargePayType.getNameByType(order.getPayType()),
                            highUser.getOpenId());
                }).start();

            } else {
                OutRechargeOrderRecord rechargeOrderRecord = rechargeOrderRecordService.findByOrderNo(dataObject.getString("out_order_id"));
                if (rechargeOrderRecord == null) {
                    rechargeOrderRecord = new OutRechargeOrderRecord();
                    // 查询订单
                    OutRechargeOrder order = outRechargeOrderService.findByOrderNo(dataObject.getString("out_order_id"));
                    if (order.getStatus() == 2) {
                        if (order.getRechargeType() == 1) {
                            String orderNo = "CZ" + DateUtil.date2String(new Date(),"yyyyMMddHHmmss") + IDGenerator.nextId(5);
                            JSONObject object =  outRechargeOrderService.getMobile(order.getRechargeContent() , order.getOrderPrice().intValue() , orderNo , order.getRechargeType());
                            if (object.getInteger("code") != 200) {
                                order.setRechargeStatus(1);
                                order.setAbnormalMsg(object.getString("message"));
                            }
                            outRechargeOrderService.updateOrder(order);
                            rechargeOrderRecord.setRechargeOrderId(order.getId());
                            rechargeOrderRecord.setRechargeOrderNo(orderNo);
                            rechargeOrderRecord.setCreateTime(new Date());
                            rechargeOrderRecord.setStatus(1);
                            rechargeOrderRecordService.insertOrder(rechargeOrderRecord);
                        }
                    }

                } else {
                    // 查询订单
                    OutRechargeOrder order = outRechargeOrderService.findByOrderId(rechargeOrderRecord.getRechargeOrderId());
                    if (order.getStatus() == 2) {
                        orderToRefund(order.getId());
                        order.setStatus(5);
                        outRechargeOrderService.updateOrder(order);
                    }
                }

            }

            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer= response.getWriter();
            writer.write("SUCCESS");


        } catch (Exception e) {
            log.error("WechatPayController --> wechatNotify() error!", e);
        }
    }


    public Boolean orderToRefund(Long orderId) {
        try {

            OutRechargeOrder order = outRechargeOrderService.findByOrderId(orderId);


            // 订单状态 ： 1.待支付 2.已支付 3.已完成 4.已取消 5.已退款 6：退款中
            if (order.getStatus() != 2) {
                log.error("orderToPay error!", "无法退款，订单状态错误！");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法退款，订单不处于已支付状态");
            }

            // 微信退款
            if (order.getPayType() == 1) {
                Map<String,String> param = new HashMap<>();
                param.put("appid", "wx637bd6f7314daa46");
                param.put("mch_id", "1289663601");
                param.put("sub_mch_id" , "1614670195");
                param.put("nonce_str", WxUtils.makeNonStr());
                param.put("transaction_id", order.getPaySerialNo());
                param.put("out_refund_no", "HFR"+new Date().getTime());
                param.put("total_fee", String.valueOf(order.getPayRealPrice().multiply(new BigDecimal("100")).intValue()));
                param.put("refund_fee", String.valueOf(order.getPayRealPrice().multiply(new BigDecimal("100")).intValue()));
                param.put("sign_type", "HMAC-SHA256");

                String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
                param.put("sign", signStr);

                String resultXmL = doRefundRequest(param.get("mch_id"), WxUtils.mapToXml(param));
                OrderRefundModel orderRefundModel = XmlUtil.getObjectFromXML(resultXmL, OrderRefundModel.class);

                if(orderRefundModel.getResult_code().equals("SUCCESS")) {
                    order.setStatus(5);
                    order.setRefundTime(new Date());
                    order.setOutRefundNo(orderRefundModel.getOut_refund_no());
                    order.setRefundId(orderRefundModel.getRefund_id());
                    order.setRefundFee(new BigDecimal(orderRefundModel.getRefund_fee()).divide(new BigDecimal("100")));
                    outRechargeOrderService.updateOrder(order);
                } else {
                    log.error("orderToPay error!", "退款失败");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！错误代码："+orderRefundModel.getErr_code()+",错误描述"+orderRefundModel.getErr_code_des());
                }
            }

            // 工会卡退款
            if (order.getPayType() == 2) {
                JSONObject jsonObject = HuiLianTongUnionCardConfig.refund( "HFR"+new Date().getTime() , order.getOrderNo());

                if (jsonObject == null) {
                    log.error("orderToPay error!", "请求超时");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "请求超时，请重新点击");
                }

                JSONObject dataObject = HuiLianTongUnionCardConfig.resolveResponse(jsonObject.getString("data"));

                if (dataObject.getBoolean("success") || Objects.equals(dataObject.getString("message"), "原交易已撤销,不可再次操作")) {
                    order.setStatus(5);
                    order.setRefundTime(new Date());
                    order.setOutRefundNo("HFR"+new Date().getTime() );
                    order.setRefundFee(order.getPayRealPrice());
                    order.setRefundId(dataObject.getString("orderId"));
                    outRechargeOrderService.updateOrder(order);

                } else {
                    log.error("orderToPay error!", dataObject.getString("message"));
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, dataObject.getString("message"));
                }
            }

            // 积分退款
            if (order.getPayType() == 3) {

                if (highUserService.findGoldRepeat(3 , order.getId())) {
                    highUserService.goldHandle(order.getUserId(), order.getPayRealPrice().multiply(BigDecimal.valueOf(100)).intValue(), 1, 3, order.getId());
                }else {
                    log.error("orderToPay error!", "已有退款记录");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "已有退款记录");
                }

            }

            // 银联退款
            if (order.getPayType() == 4) {
                // 订单退款
                JSONObject refund = UnionPayConfig.zwrefund(UnionPayConfig.MER_ID2, UnionPayConfig.TERM_ID2, order.getOrderNo(), order.getPaySerialNo(), order.getPayRealPrice().multiply(new BigDecimal("100")).longValue());
                if (!refund.getString("resultcode").equals("W6")) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, refund.getString("returnmsg"));
                }

                order.setStatus(5);
                order.setRefundTime(new Date());
                order.setOutRefundNo(refund.getString("oriwtorderid"));
                order.setRefundFee(order.getPayRealPrice());
                outRechargeOrderService.updateOrder(order);
            }

            if (order.getMemDiscountId() != null) {
                HighDiscountUserRel rel = highDiscountUserRelService.getRelById(order.getMemDiscountId());
                if (rel != null) {
                    rel.setStatus(1);  // 状态  0:已过期  1：未使用  2：已使用
                    rel.setUseTime(null);
                    highDiscountUserRelService.updateDiscountUserRel(rel);

                    HighDiscountAgentCode code = highDiscountAgentCodeService.getCodeById(rel.getDiscountAgentCodeId());
                    code.setStatus(2);
                    highDiscountAgentCodeService.updateCode(code);
                }
            }

            new Thread(() -> {
                HighUser highUser = highUserService.findByUserId(order.getUserId());
                WxMsgConfig.rechargedFail(
                        "订单号:" + order.getOrderNo() + "-" + order.getRechargeName(),
                        String.valueOf(order.getPayRealPrice()),
                        highUser.getOpenId());
            }).start();

            return true;
        } catch (Exception e) {
            log.error("HighOrderController --> getUserOrderList() error!", e);
            return false;
        }
    }


    public String doRefundRequest(String mchId,String data) throws Exception {

        //小程序退款需要调用双向证书的认证
        CloseableHttpClient httpClient = goodsOrderService.readCertificate(mchId);
        try {
            HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund"); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "text/xml");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            httpClient.close();
        }
    }
}
