package com.liquidnet.service.dragon.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.PayChannelStrategyContext;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.strategy.impl.ApplepayImpl;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.IDragonOrdersService;
import com.liquidnet.service.dragon.utils.ApplepayUtils;
import com.liquidnet.service.dragon.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
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.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.SortedMap;
import java.util.TreeMap;

@Slf4j
@Service
public class DragonOrdersServiceImpl implements IDragonOrdersService {
    @Value("${apple.urlVerify}")
    private  String appleUrl;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PayChannelStrategyContext payChannelStrategyContext;

    @Autowired
    private DataUtils dataUtils;

    @Autowired
    private DragonPayBiz dragonPayBiz;
    @Autowired
    private DragonServiceCommonBiz dragonServiceCommonBiz;
    @Autowired
    private ApplepayImpl applepay;

    @Override
    public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
        //设置支付编号
        if(dragonPayBaseReqDto.getAppIdType().equals("b")){
            dragonPayBaseReqDto.setCode(IDGenerator.payCodeByType());
        }else{
            dragonPayBaseReqDto.setCode(IDGenerator.payCode());
        }
        log.info("dragon:dragonPay:req:dragonPayBaseReqDto : {}",dragonPayBaseReqDto.toString());
        return payChannelStrategyContext.getStrategy(dragonPayBaseReqDto.getPayType()).dragonPay(dragonPayBaseReqDto);
    }

    @Override
    public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
        return payChannelStrategyContext.getStrategy(payType).dragonNotify(request,payType,deviceFrom);
    }

    @Override
    public DragonPayOrderQueryRespDto checkOrderStatusByCode(String code) {
        DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
        if(StringUtil.isEmpty(ordersDto)){
            throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
        }
        //如果已支付 直接返回结果  // MICROPAYWEPAY  MICROPAYALIPAY
        if(!ordersDto.getStatus().toString().equals(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode())&&!ordersDto.getPaymentType().equals("MICROPAYALIPAY")&&!ordersDto.getPaymentType().equals("MICROPAYWEPAY")){

            return dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
        }
        //如果未支付进行三方查询`
        String payType = DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getPayType();
        return payChannelStrategyContext.getStrategy(payType).checkOrderStatus(code);
    }

    @Override
    public boolean manulNotify(String code) {
        DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
        if(StringUtil.isEmpty(ordersDto)){
            throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
        }
        //通知商户
        return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(ordersDto));
    }

    /**
     * 苹果支付
     * @param dragonPayBaseReqDto
     */
    @Override
    public DragonPayBaseRespDto dragonNotifyApple(DragonPayBaseReqDto dragonPayBaseReqDto) {
        //1 调用苹果查询结果
        String verifyResult = buyAppVerify(dragonPayBaseReqDto.getReceiptData());
        //第二部
        //持久化通知记录
        dragonServiceCommonBiz.createDragonOrderLogs(dragonPayBaseReqDto.getCode(),dragonPayBiz.getPaymentType(dragonPayBaseReqDto.getPayType(),dragonPayBaseReqDto.getDeviceFrom()),verifyResult);
        if (verifyResult == null) {
            // 苹果服务器没有返回验证结果
            log.info("苹果支付，app调用，查不到订单信息");
            return null;
        } else {
            JSONObject job = JSONObject.parseObject(verifyResult);
            Integer states = job.getInteger("status");
            if (states==0){ // 前端所提供的收据是有效的    验证成功
      /*          String r_receipt = job.getString("receipt");
                JSONObject returnJson = JSONObject.parseObject(r_receipt);
                String in_app = returnJson.getString("in_app");
                JSONObject in_appJson = JSONObject.parseObject(in_app.substring(1, in_app.length() - 1));
                String product_id = in_appJson.getString("product_id");
                String transaction_id = in_appJson.getString("transaction_id");   // 订单号*/
                //如果单号一致  则开始处理逻辑
                //判断是已经查过了。
                DragonPayBaseRespDto dragonPayBaseRespDto=dataUtils.getDragonPayBaseRespDto(dragonPayBaseReqDto.getOrderCode());
                if(null!=dragonPayBaseRespDto){
                    return dragonPayBaseRespDto;
                }
                /*String[] moneys = product_id.split("\\.");//实际支付金额*/
                //此处开始业务逻辑
                //2 插入支付该支付的东西（预支付的东西）//dragon_orders
                dragonServiceCommonBiz.buildPayOrders(dragonPayBaseReqDto,null);
                //修改状态
                applepay.completeSuccessOrder(dataUtils.getPayOrderByCode(dragonPayBaseReqDto.getCode()),dragonPayBaseReqDto.getTransactionId(),verifyResult);
                //
                DragonPayBaseRespDto respDto = buildCommonRespDto(dragonPayBaseReqDto);
                respDto.setStatus(0);
                dataUtils.createAPPLePayOrder(dragonPayBaseReqDto.getOrderCode(),respDto);
                return respDto;
            } else {
                return null;
            }
        }
    }
    public  String buyAppVerify(String receipt) {
        try{
            SortedMap<String, Object> parameters = new TreeMap<>();
            parameters.put("receipt-data",receipt);
            String data = JSON.toJSONString(parameters);
            HttpPost httpost = new HttpPost(appleUrl);
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = ApplepayUtils.getInstance().getHttpClient().execute(httpost);
            HttpEntity entity = response.getEntity();
            //接受到返回信息
            String returnDate = EntityUtils.toString(response.getEntity(), "UTF-8");
            EntityUtils.consume(entity);
            log.info("苹果支付完成后查询{} ",returnDate);
            return returnDate;
        }catch (Exception e){
            log.error(e.getMessage());
        }

        return null;
    }
    /**
     * 构造公共返回参数
     * @param dragonPayBaseReqDto
     * @return
     */
    protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto){
        DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
        respDto.setPayType(dragonPayBaseReqDto.getPayType());
        respDto.setCode(dragonPayBaseReqDto.getCode());
        respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
        DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
        respDto.setPayData(payData);
        return respDto;
    }

}
