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

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;

import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.order.request.NeusoftMemberRechargeRequest;
import com.neusoft.smart.pos.dto.order.request.PostCreateOrderRequest;
import com.neusoft.smart.pos.dto.payorder.request.PostCreatePayOrderRequest;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.DateUtils;
import com.neusoft.smart.pos.order.constants.TradeErrorCode;
import com.neusoft.smart.pos.order.service.OrderService;
import com.neusoft.smart.pos.order.utils.WXTokenUtils;
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.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.TradeSettlementQueryService;
import com.neusoft.smart.pos.utils.PosDeviceRedisUtils;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;


@Component
public class OrderMQReceiverHelper {

    private static Logger logger = LoggerFactory.getLogger(OrderMQReceiverHelper.class);
    private static final String M_CODE = "CMB034153fbffa79";
    @Value("${smart.pos.constant.oss.endpoint}")
    private String endpoint;

    @Value("${smart.pos.constant.oss.accessId}")
    private String accessId;

    @Value("${smart.pos.constant.oss.accessKey}")
    private String accessKey;

    @Value("${smart.pos.constant.oss.host}")
    private String host;

    @Value("${smart.pos.constant.oss.bucketName}")
    private String bucketName;

    @Value("${smart.pos.constant.oss.url.host}")
    private String urlHost;

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private TradeMchPayDetailRepository tradeMchPayDetailRepository;

    @Autowired
    private TradeSettlementQueryService tradeSettlementQueryService;

    @Autowired
    private PayChannelRepository payChannelRepository;

    public void doMessage(String objectName) {
    	logger.info("消息接收者接收到来自【login队列一】的消息，消息内容:{}", objectName);
    	List<NeusoftMemberRechargeRequest> transInfoList = getOssAccountInfo(objectName);
        for(val transInfo:transInfoList){
            checkAccount(transInfo.getTransNo(), transInfo.getMemberCardNo(), transInfo.getAmount(), transInfo.getTime());
        }
    }

    private List<NeusoftMemberRechargeRequest> getOssAccountInfo(String objectName) {
        List<NeusoftMemberRechargeRequest> transInfoList = new ArrayList();
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);

        // 读取文件内容。
        System.out.println("Object content:");
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        while (true) {
            String line = null;
            try {
                line = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (line == null) break;

            System.out.println("\n" + line);
            NeusoftMemberRechargeRequest requestInfo = paserTransInfo(line);
            if(requestInfo != null){
                transInfoList.add(requestInfo);
            }
        }
        // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return transInfoList;
    }

    private NeusoftMemberRechargeRequest paserTransInfo(String line) {
        val infoArray = line.split("\\|");
        if(infoArray!=null && infoArray.length>=5) {
            /*招行对账文件示例：
            3512008120002463|159721315942166115|70367|1000|2020-08-12 14:03:32|
                 ①                ②            ③   ④           ⑤
            文件字段与与招行“1.	员工充值接口”（文档地址： https://10.100.72.23:8443/svn/SmartPos/智能POS管理系统/平台销售项目资料/沈阳食堂/东软沈阳园区餐饮系统招行接口.docx）字段对照关系：
            mcode：招行固定商户号
            sign： 签名，见员工充值接口
            memberCardNo：③
            amount：④，分为单位
            time：⑤
            transNo：①
            nonce: 自己生成的随机数，参考员工充值接口*/

            NeusoftMemberRechargeRequest info = new NeusoftMemberRechargeRequest();
            info.setTransNo(infoArray[0]);
            info.setMemberCardNo(infoArray[2]);
            info.setAmount(Long.valueOf(infoArray[3]));
            info.setTime(infoArray[4]);
            return info;
        }else{
            logger.info("账单数据有误！");
            return null;
        }
    }

    private void checkAccount(String transNo, String memberCardNo, Long orderAmount, String time) {
        val payOrder = payOrderService.getPayOrderByOuterOrderNumber(transNo);
        if (payOrder == null) {
            logger.info("对账发现订单不存在，transNo：", transNo);
            neusofCardRecharge(transNo, memberCardNo, orderAmount, time);
        } else {
            if (DictionaryConstant.PAY_STATUS_YFK.getCode().equals(payOrder.getPayStatus())) {
                logger.info("对账订单存在状态正确，transNo：", transNo);
                return;
            } else {
                logger.info("对账发现订单状态不正确，transNo：", transNo);
                logger.info("对账发现订单状态不正确，status：", payOrder.getPayStatus());
                payOrderService.updatePayOrderStatus(payOrder.getTradeId(),DictionaryConstant.PAY_STATUS_YFK.getCode());
            }
        }
    }

    private void neusofCardRecharge(String transNo, String memberCardNo, Long orderAmount, String time) {

        PostCreateOrderRequest createOrderRequest = new PostCreateOrderRequest();
        val deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(M_CODE);
        if (null == deviceInfo) {
            throw new BusinessCommonException(TradeErrorCode.DEVICE_ORG_EMPTY);
        }
        createOrderRequest.setOrgId(deviceInfo.getOrganizationId());
        createOrderRequest.setShopId(deviceInfo.getStoreId());
        createOrderRequest.setSerialNo(M_CODE);
        createOrderRequest.setOrderAmount(orderAmount);
        createOrderRequest.setOrderType(DictionaryConstant.ORDER_TYPE_HYCZ.getCode());
        createOrderRequest.setBuyerId(memberCardNo);

        val orderResponse = orderService.createOrder(createOrderRequest);

        PayOrder resultPayOrder = createSimplePayOrder(orderResponse.getOrderNumber(),
                DictionaryConstant.PAY_TYPE_CZ_ONLINE.getCode(),
                orderResponse.getOrderAmount(), "{cardNum:" + memberCardNo + "}");
        resultPayOrder.setPayTime(DateUtils.parse(time));
        resultPayOrder.setOuterOrderNumber(transNo);
        resultPayOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
        resultPayOrder.setMcode(M_CODE);

        JSONObject paramsNewJson = new JSONObject();

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

        //val result = remoteCardTradeService.balance(memberCardNo, null, null);
    }

    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;
    }

    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;
    }

}