package com.miaxis.wx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.miaxis.common.config.WxpayConfig;
import com.miaxis.common.exception.CustomException;
import com.miaxis.order.domain.OrderInfo;
import com.miaxis.order.service.IOrderInfoService;
import com.miaxis.wx.domain.RefundRecord;
import com.miaxis.wx.domain.WxJsOrder;
import com.miaxis.wx.dto.WxNotifyReturnDTO;
import com.miaxis.wx.mapper.RefundRecordMapper;
import com.miaxis.wx.mapper.WxJsOrderMapper;
import com.miaxis.wx.service.IRefundRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 微信退款记录Service业务层处理
 *
 * @author miaxis
 * @date 2021-05-18
 */
@Service
@Slf4j
public class RefundRecordServiceImpl extends ServiceImpl<RefundRecordMapper, RefundRecord> implements IRefundRecordService {
    @Resource
    private RefundRecordMapper refundRecordMapper;

    @Resource
    private WxJsOrderMapper wxJsOrderMapper;

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private HttpClient httpClient;


    @Autowired
    private WxpayConfig wxpayConfig;
    /**
     * 查询微信退款记录列表
     *
     * @param refundRecord 微信退款记录
     * @return 微信退款记录
     */
    @Override
    public List<RefundRecord> selectRefundRecordList(RefundRecord refundRecord){
        return refundRecordMapper.selectRefundRecordList(refundRecord);
    }

    @Override
    public WxNotifyReturnDTO refund(WxJsOrder wxJsOrder, String refundCode, String failCause) throws Exception{
        HttpPost httpPost = new HttpPost(wxpayConfig.getV3urlRefund());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("out_trade_no", wxJsOrder.getOutTradeNo())
                .put("out_refund_no", refundCode)
                .put("reason", failCause)
                .put("notify_url",wxpayConfig.getNotifyUrlRefund());
        rootNode.putObject("amount")
                .put("refund", wxJsOrder.getTotal())
                .put("total", wxJsOrder.getTotal())
                .put("currency", wxJsOrder.getCurrency());

//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
//        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(rootNode.toString(), "utf-8"));
        HttpResponse response = httpClient.execute(httpPost);


        // 返回数据：
        String bodyAsString = EntityUtils.toString(response.getEntity());
        if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
            log.info("退款成功，订单号:"+wxJsOrder);
            //更新这个字段
            wxJsOrder.setOutRefundNo(refundCode);
            wxJsOrder.setRefundReason(failCause);
            wxJsOrder.setTradeType("3");
            wxJsOrderMapper.updateById(wxJsOrder);
            OrderInfo orderInfo = orderInfoService.getByOutTradeNo(wxJsOrder.getOutTradeNo());
            orderInfo.setOutRefundNo(refundCode);
            orderInfo.setTradeType(3);
            orderInfo.setRefundReason(failCause);
            orderInfoService.updateById(orderInfo);


            //  保存退款数据到数据库
            RefundRecord refundRecord = new RefundRecord();
            JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
            refundRecord.setRefundId(jsonObject.getString("refund_id"));
            refundRecord.setOutRefundNo(jsonObject.getString("out_refund_no"));
            refundRecord.setTransactionId(jsonObject.getString("transaction_id"));
            refundRecord.setOutTradeNo(jsonObject.getString("out_trade_no"));
            refundRecord.setChannel(jsonObject.getString("channel"));
            refundRecord.setUserReceivedAccount(jsonObject.getString("user_received_account"));
            if (jsonObject.getString("success_time")!=null){
                refundRecord.setSuccessTime(new DateTime(jsonObject.getString("success_time")).toDate());
            }
            refundRecord.setCreateTime(new DateTime(jsonObject.getString("create_time")).toDate());
            refundRecord.setStatus(jsonObject.getString("status"));
            refundRecord.setFundsAccount(jsonObject.getString("funds_account"));
            JSONObject amount = jsonObject.getJSONObject("amount");
            refundRecord.setTotal(amount.getInteger("total"));
            refundRecord.setRefund(amount.getInteger("refund"));
            refundRecord.setPayerTotal(amount.getInteger("payer_total"));
            refundRecord.setPayerRefund(amount.getInteger("payer_refund"));
            refundRecord.setSettlementRefund(amount.getInteger("settlement_refund"));
            refundRecord.setSettlementTotal(amount.getInteger("settlement_total"));
            refundRecord.setDiscountRefund(amount.getInteger("discount_refund"));
            refundRecord.setCurrency(amount.getString("currency"));
            this.save(refundRecord);

            WxNotifyReturnDTO wxNotifyReturnDTO = new WxNotifyReturnDTO();
            wxNotifyReturnDTO.setCode("SUCCESS");
            wxNotifyReturnDTO.setMessage("成功");
            return wxNotifyReturnDTO;
        }else{
            throw new CustomException(bodyAsString);
        }

    }

    @Override
    public RefundRecord getByRefundId(String refundId) {
        return refundRecordMapper.getByRefundId(refundId);
    }
}
