package com.fs.pay.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.config.FSSysConfig;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.StringUtils;
import com.fs.store.service.IFsStoreOrderService;
import com.fs.pay.service.IPayService;
import com.fs.pay.service.dto.*;
import com.hc.openapi.tool.HcClient;
import com.hc.openapi.tool.HcGateway;
import com.hc.openapi.tool.util.Ids;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class PayServiceImpl implements IPayService {
    Logger logger= LoggerFactory.getLogger(getClass());

    @Autowired
    FSSysConfig sysConfig;
    @Autowired
    private IFsStoreOrderService orderService;

    @Override
    public R upload(UploadDTO param) {

        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("requestNo", Ids.gid());
        data.put("service", "accountpay.img.upload");
        data.put("fileName",param.getFileName());
        data.put("data",param.getData());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {
                return R.ok().put("url", responseObject.get("url"));
            }else {
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
        }
        return R.error(responseStr);
    }

    @Override
    public R openBusiness(OpenBusinessDTO param) {
        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("requestNo", Ids.gid());
        data.put("service", "accountpay.open.business");
        data.put("outUserId",param.getOutUserId());
        data.put("name",param.getName());
        data.put("shortName",param.getShortName());
        data.put("businessType",param.getBusinessType());
        data.put("licenseNo",param.getLicenseNo());
        data.put("licenseUrl",param.getLicenseUrl());
        data.put("handLicenceUrl",param.getHandLicenceUrl());
        data.put("legalName",param.getLegalName());
        data.put("legalLicenceType",param.getLegalLicenceType());
        data.put("legalCertNo",param.getLegalCertNo());
        data.put("legalLicenceFrontUrl",param.getLegalLicenceFrontUrl());
        data.put("legalLicenceBackUrl",param.getLegalLicenceBackUrl());
        data.put("contactName",param.getContactName());
        data.put("contactMobile",param.getContactMobile());
        data.put("contactCertNo",param.getContactCertNo());
        data.put("contactEmail",param.getContactEmail());
        data.put("industry",param.getIndustry());
        data.put("province",param.getProvince());
        data.put("city",param.getCity());
        data.put("district",param.getDistrict());
        data.put("address",param.getAddress());
        data.put("bankCode",param.getBankCode());
        data.put("bankCardNo",param.getBankCardNo());
        data.put("bankCardType",param.getBankCardType());
        data.put("openAccountLicenceNo",param.getOpenAccountLicenceNo());
        data.put("openAccountLicenceUrl",param.getOpenAccountLicenceUrl());
        data.put("servicePhone",param.getServicePhone());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {
                return R.ok().put("data",responseStr);
            }else {
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
        }
        return R.error(responseStr);
    }

    @Override
    public R openQuery(OpenQueryDTO param) {
        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("requestNo", Ids.gid());
        data.put("service", "accountpay.open.query");
        data.put("outUserId",param.getOutUserId());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {
                return R.ok().put("data",responseStr);
            }else {
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
        }
        return R.error(responseStr);
    }

    @Override
    public R queryFullBalance(QueryFullBalanceDTO param) {
        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("requestNo", Ids.gid());
        data.put("service", "accountpay.queryFullBalance");
        data.put("outUserId",param.getOutUserId());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {
                return R.ok().put("data",responseStr);
            }else {
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
        }
        return R.error(responseStr);
    }

    @Override
    public void createOrder(CreatePayDTO createPayDTO) {

        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("signType", "MD5");
        data.put("returnUrl", "");
        //异步通知地址
        data.put("notifyUrl", sysConfig.getPayNotifyUrl());
        //标识每次请求，每次请求必须唯一
        // Snowflake snowflake1 = IdUtil.getSnowflake(2, 2);
        // Long id = snowflake1.nextId();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        data.put("requestNo", Ids.gid());
        data.put("context","");
        data.put("service", "accountpay.order.create");
        data.put("merchOrderNo",createPayDTO.getMerchOrderNo());
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE,30);
        data.put("expiredTime",sdf.format(calendar.getTime()));
        data.put("tradeOrders",JSONUtil.toJsonStr(createPayDTO.getOrders()));
        HcClient hcClient = HcGateway.getOpenApiClientService();
        Date startTime=new Date();

        logger.info("开始时间:"+startTime.getTime());
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        Date endTime=new Date();
        logger.info("结束时间:"+endTime.getTime());
        logger.info("用时:"+(endTime.getTime()-startTime.getTime())/1000);
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            //订单创建成功
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {

            }else {
                //失败
                new CustomException("订单创建失败"+responseStr);
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
            new CustomException("订单创建验签失败"+responseStr);
        }
        new CustomException("订单创建失败"+responseStr);
    }

    @Override
    public Map<String,String> payOrder(PayDTO payDTO) {

        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId",  sysConfig.getPayPartnerId());
        data.put("signType", "MD5");
        data.put("returnUrl", "");
        data.put("notifyUrl", sysConfig.getPayNotifyUrl());
        data.put("requestNo", Ids.gid());
        data.put("context", "");
        data.put("service", "accountpay.pay");
        data.put("merchOrderNo", payDTO.getOrigMerchOrderNo());
        //原交易订单，创建订单时merchOrderNO
        data.put("origMerchOrderNo", payDTO.getOrigMerchOrderNo());
        //支付方式
        data.put("payChannel", "wx_mini");
        data.put("openID", payDTO.getOpenID());
        data.put("appID", payDTO.getAppID());
        data.put("payerOutUserId", payDTO.getPayerOutUserId());
        data.put("payerOutUserName", payDTO.getPayerOutUserName());
        data.put("userIp",payDTO.getUserIp());
        Date startTime=new Date();
        logger.info("开始时间:"+startTime.getTime());
        //执行请求
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());

        Date endTime=new Date();
        logger.info("结束时间:"+endTime.getTime());
        logger.info("用时:"+(endTime.getTime()-startTime.getTime())/1000);
        //验签
        logger.info("payXYD:"+responseStr);
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            //返回结果异常设置为处理中
            if(responseObject.get("resultCode")==null || StringUtils.isEmpty((String)responseObject.get("resultCode"))){
                //log.error("返回结果为空gid:{}",order.getGid());
                Map<String,String> map=new HashMap<>();
                map.put("code","500");
                return map;
            }
            //执行成功，判断订单状态
            if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_SUCCESS")) {
                String orderStats = (String)responseObject.get("orderStatus");
                if(StringUtils.equals(orderStats, "SUCCESS") || StringUtils.equals(orderStats, "WAIT_CONFIRM") ) {
                    //订单成功处理

                }
                Map<String,String> map=new HashMap<>();
                map.put("code","500");
                return map;
            }else if(StringUtils.equals((String)responseObject.get("resultCode"), "EXECUTE_PROCESSING")) {
                //处理中，获取主扫扫码返回的支付链接或者公众号小程序返回的JSON串
                String payInfo = (String)responseObject.get("payInfo");
                cn.hutool.json.JSONObject jsonObject=JSONUtil.parseObj(payInfo);
                Map<String,String> map=new HashMap<>();
                map.put("timeStamp",jsonObject.getStr("timeStamp"));
                map.put("nonceStr",jsonObject.getStr("nonceStr"));
                map.put("packageValue",jsonObject.getStr("package"));
                map.put("signType",jsonObject.getStr("signType"));
                map.put("paySign",jsonObject.getStr("paySign"));
                return map;
            }else {
                //执行失败
                Map<String,String> map=new HashMap<>();
                map.put("code","500");
                return map;
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
            Map<String,String> map=new HashMap<>();
            map.put("code","500");
            return map;
        }
    }

    @Override
    public R queryPayOrder(PayQueryDTO payQueryDTO) {
        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("signType", "MD5");
        data.put("requestNo", Ids.gid());
        data.put("context","");
        data.put("service", "accountpay.pay.query");
        data.put("origMerchOrderNo",payQueryDTO.getOrigMerchOrderNo());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        logger.info("queryOrder:"+responseStr);
        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            String code=responseObject.get("orderStatus").toString();
            if(code!=null&&code.equals("PROCESSING")) {
                return R.ok();
            }
            else if(code!=null&&code.equals("SUCCESS")) {
                return R.error("此订单已支付");
            }
            else if(code!=null&&code.equals("INIT")) {
                return R.ok();
            }
            else {
                //可重新支付
                return R.ok("订单已关闭或支付失败");
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
            return R.error("验签不过，进行业务逻辑处理");
        }
    }

    @Override
    public R refundOrder(RefundDTO refundDTO) {
        Map<String,String> data = new HashMap<String,String>();
        //组装公共请求参数
        data.put("partnerId", sysConfig.getPayPartnerId());
        data.put("signType", "MD5");
        data.put("returnUrl", "");
        //异步通知地址
        data.put("notifyUrl", sysConfig.getRefundNotifyUrl());
        //标识每次请求，每次请求必须唯一
        // Snowflake snowflake1 = IdUtil.getSnowflake(2, 2);
        // Long id = snowflake1.nextId();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        data.put("requestNo", Ids.gid());
        data.put("context","");
        data.put("service", "accountpay.refund");
        data.put("merchOrderNo",refundDTO.getMerchOrderNo());
        data.put("origMerchOrderNo",refundDTO.getOrigMerchOrderNo());
        data.put("amount",refundDTO.getAmount());
        HcClient hcClient = HcGateway.getOpenApiClientService();
        String responseStr = hcClient.doPost(sysConfig.getPayGateWayUrl(),data,sysConfig.getPayKey());
        logger.info("refund:"+responseStr);
        logger.info("refundDTO:"+JSONUtil.toJsonStr(refundDTO));

        //验签
        boolean isPass = hcClient.verificationSign(responseStr,sysConfig.getPayKey());
        if(isPass) {
            JSONObject responseObject = JSON.parseObject(responseStr);
            if(((Boolean)responseObject.get("success"))) {
//                if(refundDTO.getOrderId()!=null){
//                    orderService.refundOrder(refundDTO.getOrderId());
//                }
//                else{
//                }
                return R.ok("操作成功");
            }else {
                //失败
                return R.error("操作失败:"+responseStr);
            }
        }else {
            //TODO 验签不过，进行业务逻辑处理
            return R.error("验签不过，进行业务逻辑处理");
        }

    }
}
