package com.aiup.service.service.impl;

import com.aiup.service.dao.UserLicenseDao;
import com.aiup.service.domain.exception.CommonException;
import com.aiup.service.domain.query.PrePayQuery;
import com.aiup.service.domain.query.ProductListQuery;
import com.aiup.service.domain.query.UserInfoQuery;
import com.aiup.service.domain.response.AppPayParam;
import com.aiup.service.domain.response.OrderListResponse;
import com.aiup.service.domain.response.ProductListResponse;
import com.aiup.service.domain.response.WxPrePayResponse;
import com.aiup.service.entity.*;
import com.aiup.service.service.*;
import com.alibaba.fastjson.JSON;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.ExecutorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.util.*;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {
    
    @Autowired
    private ProductService productService;

    private JsapiService jsapiService;

    private NotificationConfig notificationConfig;

    private JsapiServiceExtension jsapiServiceExtension;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private PrepayOrderService prepayOrderService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private UserLicenseDao userLicenseDao;

    /**
     * 应用ID
     */
    @Value("${wxPay.appId}")
    private String appid;
    /**
     * 直连商户号
     */
    @Value("${wxPay.mchId}")
    private String mchid;
    /**
     * 回调通知地址
     */
    @Value("${wxPay.notifyUrl}")
    private String notify_url;

//    public WxPayServiceImpl(JsapiService jsapiService,NotificationConfig notificationConfig,JsapiServiceExtension jsapiServiceExtension){
//        this.jsapiService = jsapiService;
//        this.notificationConfig = notificationConfig;
//        this.jsapiServiceExtension = jsapiServiceExtension;
//    }
    
    /**
     * 发起支付请求
     *
     * @param query 支付对象
     * @return
     */
    @Override
    public WxPrePayResponse prePay(PrePayQuery query) {
        log.info("创建微信支付单，请求参数为：{}", JSON.toJSONString(query));
        //1.获取商品信息
        Product product = productService.queryById(query.getProductId());
        if(product == null || product.getIsDeleted().equals(1)){
            log.warn("创建支付单根据商品ID查询不要商品信息，productId={}",query.getProductId());
            throw  new CommonException("商品信息错误");
        }
        UserInfo userInfo = userInfoService.queryById(query.getUserId());
        if(userInfo == null || userInfo.getIsDeleted().equals(1)){
            log.warn("创建支付单根据用户ID获取不到用户信息，userId={}",query.getUserId());
            throw  new CommonException("支付用户不存在");
        }
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        //商品总金额，单位是分
        amount.setTotal(((Double)(product.getAmount()*100.00)).intValue());
        request.setAmount(amount);
        request.setAppid(appid);
        request.setMchid(mchid);
        request.setDescription(product.getProductName());
        request.setNotifyUrl(notify_url);
        //商户订单号
        String outTradeNo =  UUID.randomUUID().toString().replace("-","");
        request.setOutTradeNo(outTradeNo);
        Payer payer = new Payer();
        payer.setOpenid(userInfo.getOpenId());
        request.setPayer(payer);

        PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse = jsapiServiceExtension.prepayWithRequestPayment(request);

        String packageStr = prepayWithRequestPaymentResponse.getPackageVal();
        String perPayId = packageStr.replace("prepay_id","");
        //PrepayResponse prepay = jsapiService.prepay(request);


        log.info("微信支付单创建返回结果为：{}",JSON.toJSONString(prepayWithRequestPaymentResponse));

        //保存数据入库
        PrepayOrder prepayOrder = new PrepayOrder();
        prepayOrder.setUserId(userInfo.getUserId());
        prepayOrder.setProductId(product.getId());
        prepayOrder.setProductTotal(1);
        prepayOrder.setAmount(product.getAmount());
        prepayOrder.setTotalAmount(product.getAmount());
        prepayOrder.setAppId(appid);
        prepayOrder.setMchId(mchid);
        prepayOrder.setDescription(product.getProductName());
        prepayOrder.setNotifyUrl(notify_url);
        prepayOrder.setOutTradeNo(outTradeNo);
        prepayOrder.setPrepayId(perPayId);
        prepayOrder.setIsDeleted(0);
        prepayOrder.setIsPay(0);
        PrepayOrder insert = prepayOrderService.insert(prepayOrder);
        WxPrePayResponse response = new WxPrePayResponse();
        response.setProductId(query.getProductId());
        response.setUserId(query.getUserId());
        response.setPrepayId(perPayId);
        response.setPrepayOrderId(insert.getId());

        AppPayParam appPayParam = new AppPayParam();
        appPayParam.setNonceStr(prepayWithRequestPaymentResponse.getNonceStr());
        appPayParam.setPackageVar(prepayWithRequestPaymentResponse.getPackageVal());
        appPayParam.setSignType(prepayWithRequestPaymentResponse.getSignType());
        appPayParam.setTimeStamp(prepayWithRequestPaymentResponse.getTimeStamp());
        appPayParam.setAppId(prepayWithRequestPaymentResponse.getAppId());
        appPayParam.setPaySign(prepayWithRequestPaymentResponse.getPaySign());
        response.setAppPayParam(appPayParam);
        log.info("微信支付单创建成功,{}",JSON.toJSONString(query));

        return response;
    }

    /**
     * 获取商品列表
     *
     * @param query
     * @return
     */
    @Override
    public List<ProductListResponse> getProductList(ProductListQuery query) {
        PageRequest pageRequest = PageRequest.of(0,100);
        Product product = new Product();
        product.setIsDeleted(0);
        Page<Product> products = productService.queryByPage(product, pageRequest);

        Order order = new Order();
        order.setIsDeleted(0);
        order.setUserId(query.getUserId());
        order.setStatus(1);
        List<Order> orders = orderService.queryByPage(order, pageRequest).getContent();
        Map<String,Order> orderMap = new HashMap<>();
        for (Order o:
             orders) {
            orderMap.put(o.getProductId()+"",o);
        }
        List<ProductListResponse> list = new ArrayList<>();
        for (Product pro: products
             ) {
            ProductListResponse res = new ProductListResponse();
            BeanUtils.copyProperties(pro,res);
            if(orderMap.containsKey(pro.getId()+"")){
                res.setIsPay(1);
            }
            else{
                res.setIsPay(0);
            }
            list.add(res);
        }
        return list;
    }

    /**
     * 支付是否成功
     *
     * @param query
     * @return
     */
    @Override
    public Boolean getIsPay(WxPrePayResponse query) {
        PageRequest pageRequest = PageRequest.of(0,100);
        Order order = new Order();
        order.setPrepayOrderId(query.getPrepayOrderId());
        order.setIsDeleted(0);
        order.setUserId(query.getUserId());
        order.setStatus(1);
        return orderService.queryByPage(order,pageRequest).getTotalElements()>0;
    }

    /**
     * 微信支付回调
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public Map<String, Object> payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        try {
            //获取body
            BufferedReader reader = request.getReader();
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
            String body = stringBuilder.toString();
            //获取回调参数中的信息
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(request.getHeader("Wechatpay-Serial"))
                    .nonce(request.getHeader("Wechatpay-Nonce"))
                    .signature(request.getHeader("Wechatpay-Signature"))
                    .timestamp(request.getHeader("Wechatpay-Timestamp"))
                    .body(body)
                    .build();
            //解密
            NotificationParser notificationParser = new NotificationParser(this.notificationConfig);
            Transaction parse =notificationParser.parse(requestParam, Transaction.class);
            log.info("微信支付回调解析成功：{}",JSON.toJSONString(parse));
            //流水单号
            String outTradeNo = parse.getOutTradeNo();
            PrepayOrder prepayOrder = new PrepayOrder();
            prepayOrder.setIsDeleted(0);
            prepayOrder.setOutTradeNo(outTradeNo);
            PageRequest pageRequest = PageRequest.of(0,100);
            List<PrepayOrder> content = prepayOrderService.queryByPage(prepayOrder, pageRequest).getContent();
            prepayOrder = content.get(0);
            //更新支付单为已支付状态
            prepayOrder.setIsPay(1);
            prepayOrder.setPayTime(new Date());
            prepayOrder.setUpdateTime(new Date());
            prepayOrder = prepayOrderService.update(prepayOrder);
            //生成订单
            Order order = new Order();
            order.setPrepayOrderId(prepayOrder.getId());
            order.setStatus(1);
            order.setIsDeleted(0);
            order.setUserId(prepayOrder.getUserId());
            order.setProductId(prepayOrder.getProductId());
            orderService.insert(order);

            //增加授权许可
            UserLicense qUserLicense = new UserLicense();
            qUserLicense.setIsDeleted(0);
            qUserLicense.setUserId(prepayOrder.getUserId());
            PageRequest pageRequestLicense = PageRequest.of(0,5);
            List<UserLicense> llist = userLicenseDao.queryAllByLimit(qUserLicense, pageRequestLicense);
            boolean isNew =false;
            UserLicense license = null;
            if(llist != null && llist.size()>0){
                license = llist.get(0);
            }
            else {
                isNew = true;
                license = new UserLicense();
                license.setUserId(prepayOrder.getUserId());
                license.setIsDeleted(0);
                license.setBeginTime(new Date());
                license.setEndTime(new Date());
            }
            Product product = productService.queryById(prepayOrder.getProductId());
            Integer day = product.getDays();
            Calendar c = Calendar.getInstance();
            if(license.getEndTime().getTime() < (new Date()).getTime() ){
                c.setTime(new Date());
            }
            else {
                c.setTime(license.getEndTime());
            }
            c.add(Calendar.DATE, day);
            license.setEndTime(c.getTime());
            if(isNew){
                userLicenseDao.insert(license);
            }
            else{
                userLicenseDao.update(license);
            }
            Map<String, Object> stringObjectMap = new HashMap<>();
            //成功则响应SUCCESS
            stringObjectMap.put("code","SUCCESS");
            return stringObjectMap;
        } catch (Exception e) {
            log.error(e.toString());
            throw  e ;
        }

    }

    /**
     * 获取用户订单列表
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderListResponse> getOrderList(UserInfoQuery query) {
        return prepayOrderService.getOrderList(query);
    }
}
