package com.jpsoft.shinestar.modules.pay.alipay;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.ijpay.alipay.AliPayApi;
import com.jpsoft.shinestar.modules.base.entity.*;
import com.jpsoft.shinestar.modules.base.service.*;
import com.jpsoft.shinestar.modules.business.entity.BillPush;
import com.jpsoft.shinestar.modules.business.service.BillPushService;
import com.jpsoft.shinestar.modules.common.dto.MessageResult;
import com.jpsoft.shinestar.modules.common.service.IRedisService;
import com.jpsoft.shinestar.modules.common.utils.ParkApiUtil;
import com.jpsoft.shinestar.modules.pay.properties.AliPayProperties;
import com.jpsoft.shinestar.modules.pay.properties.ParkAliPayProperties;
import com.jpsoft.shinestar.modules.wechat.vo.UserInfo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 墨鱼_mo
 * @date 2019-11-26 9:48
 */

@Slf4j
@RequestMapping("/aliPay")
@RestController
public class AlipayController {


    @Autowired
    private AliPayProperties aliPayProperties;

    @Autowired
    private BillPushService billPushService;

    @Autowired
    private ParkingInfoService parkingInfoService;

    @Autowired
    private ParkAliPayProperties parkAliPayProperties;

    @Autowired
    private RechargeRecordService rechargeRecordService;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private ElectricClientInfoService electricClientInfoService;

    @Autowired
    private ParkingRecordService parkingRecordService;

    @Autowired
    private CompanyPaymentInfoService companyPaymentInfoService;

    @Autowired
    private IRedisService redisService;

    @Autowired
    private ParkApiUtil parkApiUtil;

    @Autowired
    private ParkingDeviceService parkingDeviceService;



    /*@ApiOperation(value = "支付宝扫码支付")
    @GetMapping("/tradePrecreatePay")
    public MessageResult tradePrecreatePay(String recordId) {

        MessageResult result = new MessageResult();

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(aliPayProperties.getServiceUrl(), aliPayProperties.getAppId(), aliPayProperties.getPrivateKey(), "json", aliPayProperties.getInputCharset(), aliPayProperties.getZfbPublicKey(), aliPayProperties.getSignType());
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            request.setNotifyUrl(aliPayProperties.getNotifyUrl());

            RechargeRecord rechargeRecord = rechargeRecordService.get(recordId);

            if (rechargeRecord == null) {
                throw new Exception("订单不存在");
            }
            if (rechargeRecord.getBuyAmount().compareTo(BigDecimal.ZERO) != 1) {
                throw new Exception("金额有误");
            }
            if (rechargeRecord.getPaymentStatus().equals("20")) {
                throw new Exception("订单已支付");
            }


            Map<String, Object> maps = new HashMap<>();
            maps.put("out_trade_no", rechargeRecord.getSerialNumber());
            maps.put("total_amount", String.valueOf(rechargeRecord.getBuyAmount()));
            maps.put("subject", rechargeRecord.getProductTheme());
            maps.put("timeout_express", "5m");

           *//* JSONObject extendParams = new JSONObject();

            extendParams.put("sys_service_provider_id", aliPayProperties.getMchId());
            maps.put("extend_params", extendParams);
            request.putOtherTextParam("app_auth_token", aliPayProperties.getAppAuthToken());*//*
            //把订单信息转换为json对象的字符串
            String postdata = JSONObject.toJSONString(maps);
            request.setBizContent(postdata);
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            String body = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String alipayTradePrecreateResponse = jsonObject.getString("alipay_trade_precreate_response");
            JSONObject jsonResponse = JSONObject.parseObject(alipayTradePrecreateResponse);

            if (!jsonResponse.getString("code").equals("10000")) {
                throw new Exception(jsonResponse.getString("sub_msg"));
            }

            String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
            result.setResult(true);

            log.warn("qr_code=" + qr_code);
            result.setData(qr_code);

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            result.setResult(false);
            result.setMessage(e.getMessage());
        }
        return result;

    }*/

    @RequestMapping(value="/payNotify")
    public String payNotify(HttpServletRequest request) {
        try {
            // 获取支付宝POST过来反馈信息

            Map<String, String> params = AliPayApi.toMap(request);

            for (Map.Entry<String, String> entry : params.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }

            boolean verifyResult = AlipaySignature.rsaCheckV1(params, aliPayProperties.getZfbPublicKey(), "UTF-8", "RSA2");

            if (verifyResult) {


                OrderInfo orderInfo = orderInfoService.findByOutOrderNo(params.get("out_trade_no"));
                String payFee = params.get("total_amount");
                if (orderInfo == null) {
                    throw new Exception("支付已完成，但未找到此订单号的流水");
                }

                orderInfo.setUpdateTime(new Date());
                orderInfo.setUpdateBy(params.get("buyer_logon_id"));
                orderInfo.setPayName("alipay");
                orderInfo.setPayStatus(20);
                orderInfo.setPayFee(new BigDecimal(payFee));
                orderInfo.setTransactionId(params.get("trade_no"));
                orderInfo.setPayTime(DateUtil.parse(params.get("gmt_payment")));
                orderInfoService.update(orderInfo);
              //  orderLogService.insert2(new OrderLog(orderInfo.getId(),"支付完成",orderInfo.getCreateBy()));


                try {
                    new Thread(() -> {
                       /* //根据订单类型做各自处理
                        orderInfoService.orderNotifyLogical(orderInfo);

                        //商户分账记录写入
                        merchantShareRecordService.insertShareRecord(orderInfo);*/

                        try{
                            //根据订单类型做各自处理
                            orderInfoService.orderNotifyLogical(orderInfo);
                        }catch (Exception ex){
                            /*SysLog sysLog = new SysLog();
                            sysLog.setRemark(ex.getMessage());
                            sysLog.setData(orderInfo.toString());
                            sysLog.setPointcut("支付");
                            sysLog.setCreateTime(new Date());
                            sysLogService.insert(sysLog);*/

                        }

                        try{

                            //支付成功向收款人发送消息
                            BillPush billPush = billPushService.findByOrderId(orderInfo.getId());
                            billPushService.sendAccountRemind(billPush);

                        }catch (Exception ex){
                            log.error(ex.getMessage(),ex);
                        }




                    }).start();
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }



                return "success";
            } else {
                log.error("notify_url 验证失败");
                return "failure";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return "failure";
        }
    }

    /*@ApiOperation(value = "停车支付宝扫码支付")
    @PostMapping("/parkTradePrecreatePay")
    public MessageResult parkTradePrecreatePay(@RequestBody HashMap<String, String> map) {

        MessageResult result = new MessageResult();

        try {
            ParkingRecord parkingRecord = parkingRecordService.get(map.get("id"));
            if (parkingRecord == null){
                throw new Exception("订单不存在");
            }
            CompanyPaymentInfo companyPaymentInfo = companyPaymentInfoService.findByCompanyId(parkingRecord.getCompanyId());
            if (companyPaymentInfo == null){
                throw new Exception("公司未配置收款账户");
            }

            AlipayClient alipayClient = new DefaultAlipayClient(aliPayProperties.getServiceUrl(), aliPayProperties.getAppId(), aliPayProperties.getPrivateKey(), "json", aliPayProperties.getInputCharset(), aliPayProperties.getZfbPublicKey(), aliPayProperties.getSignType());
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            request.setNotifyUrl(companyPaymentInfo.getParkingAlipayNotifyUrl());



            if (parkingRecord.getPayAmount().compareTo(BigDecimal.ZERO) != 1) {
                throw new Exception("金额有误");
            }
            if (parkingRecord.getPayStatus().equals("20")) {
                throw new Exception("订单已支付");
            }


            Map<String, Object> maps = new HashMap<>();
            maps.put("out_trade_no", parkingRecord.getSerialNumber());
            maps.put("total_amount", String.valueOf(parkingRecord.getPayAmount()));
            maps.put("subject", parkingRecord.getProductTheme());
            maps.put("timeout_express", "5m");

            JSONObject extendParams = new JSONObject();

            extendParams.put("sys_service_provider_id", aliPayProperties.getMchId());
            maps.put("extend_params", extendParams);
            request.putOtherTextParam("app_auth_token", companyPaymentInfo.getAppAuthToken());
            //把订单信息转换为json对象的字符串
            String postdata = JSONObject.toJSONString(maps);
            request.setBizContent(postdata);
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            String body = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String alipayTradePrecreateResponse = jsonObject.getString("alipay_trade_precreate_response");
            JSONObject jsonResponse = JSONObject.parseObject(alipayTradePrecreateResponse);

            if (!jsonResponse.getString("code").equals("10000")) {
                throw new Exception(jsonResponse.getString("sub_msg"));
            }

            String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
            result.setResult(true);

            log.warn("qr_code=" + qr_code);
            result.setData(qr_code);

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            result.setResult(false);
            result.setMessage(e.getMessage());
        }
        return result;

    }*/


    @ApiOperation(value = "停车支付宝手机网站支付")
    @PostMapping("/parkingTradeWebPay")
    public MessageResult parkingTradeWebPay(String id, String openId) {

        MessageResult result = new MessageResult();

        try {
            if (StrUtil.isBlank(openId)){
                throw new Exception("openId不存在");
            }

            if (StrUtil.isBlank(id)){
                throw new Exception("订单不存在");
            }



            ParkingRecord parkingRecord = parkingRecordService.get(id);

            parkingRecord.setOpenId(openId);
            parkingRecordService.update(parkingRecord);
            if (parkingRecord == null){
                throw new Exception("订单不存在");
            }
            ParkingInfo parkingInfo = parkingInfoService.findByParkId(parkingRecord.getParkId());

            CompanyPaymentInfo companyPaymentInfo = companyPaymentInfoService.findByCompanyId(parkingInfo.getCompanyId());
            if (companyPaymentInfo == null){
                throw new Exception("公司未配置收款账户");
            }




            AlipayClient alipayClient = new DefaultAlipayClient(parkAliPayProperties.getServiceUrl(), parkAliPayProperties.getAppId(), parkAliPayProperties.getPrivateKey(), "json", parkAliPayProperties.getInputCharset(), parkAliPayProperties.getZfbPublicKey(), parkAliPayProperties.getSignType());
            AlipayTradeCreateRequest request = new AlipayTradeCreateRequest ();
            request.setNotifyUrl(companyPaymentInfo.getParkingAlipayNotifyUrl());



            if (parkingRecord.getPayAmount().compareTo(BigDecimal.ZERO) != 1) {
                throw new Exception("金额有误");
            }
            if (parkingRecord.getPayStatus().equals("20")) {
                throw new Exception("订单已支付");
            }


            Map<String, Object> maps = new HashMap<>();
            maps.put("out_trade_no", parkingRecord.getSerialNumber());
            maps.put("total_amount", String.valueOf(parkingRecord.getPayAmount()));
            maps.put("subject", parkingRecord.getProductTheme());
            maps.put("timeout_express", "5m");
            maps.put("buyer_id", parkingRecord.getOpenId());

            JSONObject extendParams = new JSONObject();

            extendParams.put("sys_service_provider_id", parkAliPayProperties.getMchId());
            maps.put("extend_params", extendParams);
            request.putOtherTextParam("app_auth_token", companyPaymentInfo.getAppAuthToken());
            //把订单信息转换为json对象的字符串
            String postdata = JSONObject.toJSONString(maps);
            request.setBizContent(postdata);
            AlipayTradeCreateResponse response = alipayClient.execute(request);
            if(response.isSuccess()){

                HashMap<String,Object> dataMap = new HashMap<String,Object>();

                dataMap.put("tradeNo", response.getTradeNo());

                HashMap<String,Object> resultMap = new HashMap<String,Object>();

                resultMap.put("tradeOrder", dataMap);

                result.setData(resultMap);
                result.setResult(true);

            } else {
                result.setResult(false);
                result.setData("");

            }



        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            result.setResult(false);
            result.setCode(400);
            result.setMessage(e.getMessage());
        }
        return result;

    }

    @RequestMapping(value="/parkingAlipayNotify")
    public String parkingAlipayNotify(HttpServletRequest request) {

        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = AliPayApi.toMap(request);

            for (Map.Entry<String, String> entry : params.entrySet()) {
                log.warn(entry.getKey() + " = " + entry.getValue());
            }

            boolean verifyResult = AlipaySignature.rsaCheckV1(params, parkAliPayProperties.getZfbPublicKey(), "UTF-8", "RSA2");

            if (verifyResult) {

                ParkingRecord parkingRecord = parkingRecordService.findBySerialNumber(params.get("out_trade_no"));
                if (parkingRecord == null) {
                    throw new Exception("支付已完成，但未找到此订单号的流水");
                }
               /* if (!parkingRecord.getPayAmount().toString().equals(params.get("buyer_pay_amount"))) {
                    throw new Exception("支付金额与系统金额不一致");
                }*/
                parkingRecord.setUpdateTime(new Date());
                parkingRecord.setUpdateBy(params.get("buyer_logon_id"));
                parkingRecord.setPayType("alipay");
                parkingRecord.setPayStatus(20);
                parkingRecord.setTransactionNumber(params.get("trade_no"));
                parkingRecord.setPaymentTime(DateUtil.parse(params.get("gmt_payment")));
                parkingRecordService.update(parkingRecord);
                try {
                    parkingRecordService.payNotify(parkingRecord.getId());
                } catch (Exception e) {
                    log.error(e.getMessage(),e);
                }
                return "success";
            } else {
                log.error("notify_url 验证失败");
                return "failure";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return "failure";
        }
    }


    @GetMapping(value="findUserInfo/{authCode}")
    public MessageResult findUserInfo(@PathVariable(name="authCode") String authCode){

        System.out.println("获取支付宝的userId");
        try{

            AlipayClient alipayClient = new DefaultAlipayClient(parkAliPayProperties.getServiceUrl(),parkAliPayProperties.getAppId(),parkAliPayProperties.getPrivateKey(),parkAliPayProperties.getFormat(),parkAliPayProperties.getInputCharset(),parkAliPayProperties.getZfbPublicKey(),parkAliPayProperties.getSignType());

            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setCode(authCode);
            request.setGrantType("authorization_code");

            AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);

            System.out.println(oauthTokenResponse.getUserId());

            HashMap<String,Object> dataMap = new HashMap<String,Object>();

            UserInfo userInfo = new UserInfo();
            userInfo.setOpenid(oauthTokenResponse.getUserId());
       //     dataMap.put("openId", oauthTokenResponse.getUserId());

         //   HashMap<String,Object> resultMap = new HashMap<String,Object>();

        //    resultMap.put("userInfo", dataMap);

            return new MessageResult(true, "获取支付宝信息成功", userInfo,200);
        } catch (AlipayApiException e) {



            //处理异常
            e.printStackTrace();
            return new MessageResult(false, "获取支付宝授权失败", "",400);
        } catch (Exception e) {
            //处理异常
            e.printStackTrace();
            return new MessageResult(false, "获取支付宝授权失败", "",400);
        }
    }


    @ApiOperation(value = "支付宝扫码支付")
    @GetMapping("/tradePrecreatePay")
    public MessageResult tradePrecreatePay(String orderId,String popularizePersonId) {

        MessageResult result = new MessageResult();

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(aliPayProperties.getServiceUrl(), aliPayProperties.getAppId(), aliPayProperties.getPrivateKey(), "json", aliPayProperties.getInputCharset(), aliPayProperties.getZfbPublicKey(), aliPayProperties.getSignType());
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            request.setNotifyUrl(aliPayProperties.getNotifyUrl());

            OrderInfo orderInfo = orderInfoService.get(orderId);

            if (orderInfo == null) {
                throw new Exception("订单不存在");
            }
            if (orderInfo.getTotalFee().compareTo(BigDecimal.ZERO) != 1) {
                throw new Exception("金额有误");
            }
            if (orderInfo.getPayStatus() != 10) {
                throw new Exception("订单状态有误");
            }


            orderInfo.setPopularizePersonId(popularizePersonId);
            orderInfoService.update(orderInfo);

            String appAuthToken = aliPayProperties.getAppAuthToken();
            //查询账单收款账户
            BillPush billPush = billPushService.findByOrderId(orderId);
            if (billPush !=null){
                CompanyPaymentInfo companyPaymentInfo = companyPaymentInfoService.get(Long.valueOf(billPush.getCollectionAccountId()));

                if (companyPaymentInfo!=null){
                    appAuthToken = companyPaymentInfo.getAppAuthToken();
                }
            }





            Map<String, Object> maps = new HashMap<>();
            maps.put("out_trade_no", orderInfo.getOutOrderNo());
            maps.put("total_amount", String.valueOf(orderInfo.getTotalFee()));
            maps.put("subject", orderInfo.getBody());
            maps.put("timeout_express", "5m");

            JSONObject extendParams = new JSONObject();

            extendParams.put("sys_service_provider_id", aliPayProperties.getMchId());
            maps.put("extend_params", extendParams);
            request.putOtherTextParam("app_auth_token",appAuthToken);
            //把订单信息转换为json对象的字符串
            String postdata = JSONObject.toJSONString(maps);
            request.setBizContent(postdata);
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            String body = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String alipayTradePrecreateResponse = jsonObject.getString("alipay_trade_precreate_response");
            JSONObject jsonResponse = JSONObject.parseObject(alipayTradePrecreateResponse);

            if (!jsonResponse.getString("code").equals("10000")) {
                throw new Exception(jsonResponse.getString("sub_msg"));
            }

            String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
            result.setResult(true);

            log.warn("qr_code=" + qr_code);
            result.setData(qr_code);

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            result.setResult(false);
            result.setMessage(e.getMessage());
        }
        return result;

    }


}
