package com.videoweb.ying.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.videoweb.utils.*;
import net.sf.json.JSONObject;

import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.videoweb.base.BaseController;
import com.videoweb.utils.redis.CacheUtil;
import com.videoweb.ying.po.TExtendPrice;
import com.videoweb.ying.po.TExtensionHistory;
import com.videoweb.ying.po.TMember;
import com.videoweb.ying.po.TMemberLogin;
import com.videoweb.ying.po.TPaySetting;
import com.videoweb.ying.po.TVip;
import com.videoweb.ying.po.TVipHistory;
import com.videoweb.ying.service.TExtendPriceService;
import com.videoweb.ying.service.TExtensionHistoryService;
import com.videoweb.ying.service.TMemberLoginService;
import com.videoweb.ying.service.TMemberService;
import com.videoweb.ying.service.TPaySettingService;
import com.videoweb.ying.service.TRateService;
import com.videoweb.ying.service.TVipHistoryService;
import com.videoweb.ying.service.TVipService;

@RestController
public class ApiPayController extends BaseController{

    @Autowired
    private TVipService tVipService;

    @Autowired
    private TPaySettingService tPaySettingService;

    @Autowired
    private TVipHistoryService tVipHistoryService;

    @Autowired
    private TMemberService tMemberService;

    @Autowired
    private TMemberLoginService tMemberLoginService;

    /*@Autowired
    private TReportService tReportService;
    */

    @Autowired
    private TRateService tRateService;

    @Autowired
    private TExtensionHistoryService tExtensionHistoryService;

    @Autowired
    private TExtendPriceService tExtendPriceService;


    @PostMapping("/openapi/getPayType")
    public Object getPayType(ModelMap modelMap, HttpServletRequest request)
    {
        List<Map<String,Object>> tPaySetting = new ArrayList<Map<String,Object>>();
        tPaySetting = tPaySettingService.getPayType();
        if(tPaySetting != null && tPaySetting.size()>0)
        {
            for(Map<String,Object> tf:tPaySetting)
            {
                if("1".equals(tf.get("payImgType").toString()))
                {
                    tf.put("payImg", PropertiesUtil.getString("remote.file.uri.prefix")+tf.get("payImg"));
                }
            }
        }
        modelMap.put("retCode", "1");
        modelMap.put("retMsg", "充值方式!");

        return setSuccessResponse(modelMap,tPaySetting);
    }

    /**
     * 充值接口
     * @param modelMap
     * @param request
     * @param params
     * @return
     */
    @PostMapping("/ying/payRecharge")
    public Object payRecharge(ModelMap modelMap, HttpServletRequest request, @RequestBody Map<String, Object> params)
    {
        Integer memberId = getCurrUser(request);
        if(params == null || "".equals(params))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "充值失败,参数异常!");

            return setSuccessResponse(modelMap);
        }

        if(params.get("vipId") == null || "".equals(params.get("vipId"))
                ||params.get("payType") == null || "".equals(params.get("payType")))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "充值失败,参数异常!");
            return setSuccessResponse(modelMap);
        }

        //根据vipId取出充值价格
        TVip vip= new TVip();
        vip.setId(Integer.valueOf(params.get("vipId").toString()));
        vip = tVipService.selectOne(vip);
        if(vip == null || "".equals(vip))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "充值失败,无此产品!");
            return setSuccessResponse(modelMap);
        }
        Double price = vip.getPrice();
        int useCron = 0;
        boolean selectflag = false;
        if(params.get("selectType") != null && !"".equals(params.get("selectType")))
        {
            //当选择钻石抵扣方式时
            if("1".equals(params.get("selectType")))
            {
                selectflag = true;
                //将个人钻石数放进缓存
                TMember tmeb = new TMember();
                tmeb.setId(memberId);
                tmeb = tMemberService.selectOne(tmeb);
                //获取能够折算的金额和钻石
                Integer currentCronNum = tmeb.getCronNum();
                //获取提现手续费
                Map<String,Object> rateResult = new HashMap<String,Object>();
                rateResult = tRateService.selectRate();
                if(rateResult != null && !"".equals(rateResult))
                {
                    Double  cronRate= Double.valueOf(rateResult.get("cronRate").toString());
                    Double cc = new BigDecimal(1/cronRate).doubleValue();
                    Double tkprice = DoubleUtil.multiplyForRoundHalfUp(Double.valueOf(currentCronNum), cc, 2);

                    Integer mostPrice = Double.valueOf(rateResult.get("mostPrice").toString()).intValue();
                    Integer cronRateInt = cronRate.intValue();
                    Integer tf =mostPrice*cronRateInt;
                    //获取最大能抵扣的钻石数
                    Double usePrice = 0d;
                    if(currentCronNum>=tf)
                    {
                        useCron = tf;
                        usePrice = Double.valueOf(rateResult.get("mostPrice").toString());
                    }
                    else
                    {
                        useCron = currentCronNum;
                        usePrice = tkprice;
                    }
                    //获取扣减后的充值价格
                    price = DoubleUtil.subtractForRoundHalfUp(price,usePrice,2);
                }
            }
        }
        Integer payType = Integer.valueOf(params.get("payType").toString());
        if(payType == 1)
        {
            //支付宝
            //查询可用的支付宝账户
            TPaySetting paySetting = new TPaySetting();
            paySetting.setPayType(payType);
            paySetting.setIsEnable(1);
            paySetting = tPaySettingService.selectOne(paySetting);
            if(paySetting == null && "".equals(paySetting))
            {
                modelMap.put("retCode", "-1");
                modelMap.put("retMsg", "充值失败,第三方支付接口异常!");
                return setSuccessResponse(modelMap);
            }
            /**
             * 封装支付的params: 商户号 随机订单号 回调地址 价格 商品名称(卡的类型) 商品描叙 attach  signType sign
             */
            Map<String,String> payParams = new HashMap<String,String>();
            payParams.put("merchant_no", paySetting.getPayAccount());//商户号
            SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss");
            String merchantOrderNo =IdWorker.get32UUID() ;
            payParams.put("merchant_order_no",merchantOrderNo);//商户订单号
            payParams.put("notify_url", PropertiesUtil.getString("payBackUrl")); //回调地址
            payParams.put("start_time", tf.format(new Date()));
            Double tprice = DoubleUtil.getTwoDecimal(price);
            payParams.put("trade_amount", tprice+"");
            String goodsName="";
            if(vip.getCardType() ==1)
            {
                goodsName="月卡";
            }
            else if(vip.getCardType() ==2)
            {
                goodsName="季卡";
            }
            else if(vip.getCardType() ==3)
            {
                goodsName="年卡";
            }
            payParams.put("goods_name",goodsName);
            payParams.put("goods_desc", "购买"+goodsName);
            //形成attach串
            String attach = memberId+"ying"+price+"ying"+vip.getId()+"ying"+vip.getCardType();
            payParams.put("sign_type", "1");
            //创建sign
            String sign = createSign(payParams,paySetting.getPayKey());
            payParams.put("sign", sign);
            //加密数据
            String cc = packageSign(payParams,false);


            AlipayTradeAppPayRequest requests = new AlipayTradeAppPayRequest();
            requests.setNotifyUrl(PropertiesUtil.getString("payBackUrl"));
            // requests.setNotifyUrl("http://api.ysfu.net:8081/openapi/payBacks");//商户外网可以访问的异步地址 -- @link com.ddzn.project.tpartySupport completeOrder()
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody("购买"+goodsName);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。--可选
            model.setSubject(goodsName);//商品的标题/交易标题/订单标题/订单关键字等。--必填
            model.setOutTradeNo(merchantOrderNo);//商户网站唯一订单号。--必填 todo
            model.setTimeoutExpress("90m");//该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。 --可选
            model.setTotalAmount(String.valueOf(tprice)); //订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] --必填 todo
            model.setProductCode("QUICK_MSECURITY_PAY");//销售产品码,商家和支付宝签约的产品码,为固定值 QUICK_MSECURITY_PAY
            requests.setBizModel(model);

            AlipayTradeAppPayResponse response = null;
            try {
                response = AlipayUtil.getDefaultAlipayClient(paySetting.getGateway(), paySetting.getAppid(), paySetting.getAppPrivateKey(), "JSON", "UTF-8", paySetting.getPublickKey(), "RSA2").sdkExecute(requests);
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            System.out.println(response.getBody());
            // modelMap.put("attach",attach);
            modelMap.put("tradeNo",response.getBody());
            modelMap.put("payUrl",null);
            modelMap.put("retCode", "1");
            modelMap.put("retMsg", "发起支付成功!");


            TVipHistory tvh = new TVipHistory();
            tvh.setMemberId(memberId);
            tvh.setPayPrice(price);
            tvh.setVipId(vip.getId());
            tvh.setPayNo(merchantOrderNo);
            if(selectflag)
            {
                tvh.setIsUseCron(2);
                tvh.setUseCron(useCron);
            }

            if(vip.getCardType()==1)
            {
                tvh.setDateValidity(30);
            }
            else if(vip.getCardType()==2)
            {
                tvh.setDateValidity(90);
            }
            else if(vip.getCardType()==3)
            {
                tvh.setDateValidity(365);
            }
            tvh.setAttach(attach);
            tvh.setPayStatus(1);//待支付
            tvh.setPayType(1);
            tVipHistoryService.update(tvh);

        }

        return setSuccessResponse(modelMap);
    }


    @Resource
    HttpServletRequest request;

    @PostMapping("/openapi/payBacks")
    public String completeOrder() {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        TPaySetting paySetting = new TPaySetting();
        paySetting.setPayType(1);
        paySetting.setIsEnable(1);
        paySetting = tPaySettingService.selectOne(paySetting);
        String orderNumber = params.get("out_trade_no"); //本地订单编号
        //TODO 修改订单状态,生成会员卡信息
        try {
            boolean flag = AlipaySignature.rsaCheckV1(params, paySetting.getPublickKey(), "utf-8","RSA2");
            if(flag){

                String merchantOrderNo =orderNumber;
                TVipHistory tvh = new TVipHistory();
                tvh.setPayNo(merchantOrderNo);
                tvh.setPayStatus(1);
                tvh = tVipHistoryService.selectOne(tvh);
                // String tradeNo = params.get("tradeNo").toString();
                String attach = tvh.getAttach();
                String[] sf = attach.split("ying");
                if(tvh == null ||"".equals(tvh))
                {
                    return "fail";
                }
                tvh.setPayTime(new Date());
                tvh.setPayStatus(2);
                // tvh.setPayOutNo(tradeNo);
                tVipHistoryService.update(tvh);
                //更新用户VIP,及其使用期限
                TMember tmb = new TMember();
                tmb.setId(Integer.valueOf(sf[0]));
                tmb = tMemberService.selectOne(tmb);
                tmb.setIsVip(1);
                tmb.setVipId(Integer.valueOf(sf[2]));
                Date oldDay = tmb.getVipDate();
                if(oldDay == null || "".equals(oldDay))
                {
                    oldDay = new Date();
                }
                Calendar ca = Calendar.getInstance();
                ca.setTime(oldDay);
                if(Integer.valueOf(sf[3])==1)
                {
                    ca.add(Calendar.DATE, 30);
                }
                else if(Integer.valueOf(sf[3])==2)
                {
                    ca.add(Calendar.DATE, 90);;
                }
                else if(Integer.valueOf(sf[3])==3)
                {
                    ca.add(Calendar.DATE, 365);
                }
//                TVip tVip = new TVip();
//                tVip.setId(Integer.valueOf(sf[2]));
//                tVip = tVipService.selectOne(tVip);
//                tmb.setCacheNum(tVip.getCacheNum());
                Date cc = ca.getTime();
                tmb.setVipDate(cc);
                //扣除钻石数
                if(tvh.getIsUseCron() == 2)
                {
                    if(tmb.getCronNum().intValue()>tvh.getUseCron().intValue())
                    {
                        int newCrom = tmb.getCronNum()-tvh.getUseCron();
                        tmb.setCronNum(newCrom);
                    }
                }
                tMemberService.update(tmb);
                //更改充值
                //获取渠道码
                TMemberLogin ml = new TMemberLogin();
                ml.setMemberId(Integer.valueOf(sf[0]));
                ml = tMemberLoginService.selectOne(ml);
                this.getReportCache(3, ml.getFromCode(), String.valueOf(tvh.getPayPrice()));

                //进行充值分配钻石
                //获取后台比例
                Map<String,Object> tf = new HashMap<String,Object>();
                tf = tRateService.selectRate();
                if(tf != null && !"".equals(tf))
                {
                    if(tf.get("rechargeRate") != null && !"".equals(tf.get("rechargeRate")))
                    {
                        Double rechargeRate = Double.valueOf(tf.get("rechargeRate").toString());
                        Double cronNumDouble= DoubleUtil.multiplyForRoundHalfUp(tvh.getPayPrice(),rechargeRate,0);
                        int cronNumNew =cronNumDouble.intValue();
                        //获取被推广人的金币
                        TExtensionHistory tex = new TExtensionHistory();
                        tex.setExtendId(tvh.getMemberId());
                        tex=tExtensionHistoryService.selectOne(tex);
                        if(tex != null && !"".equals(tex))
                        {
                            TMember extendMember = new TMember();
                            extendMember.setId(tex.getMemberId());
                            extendMember = tMemberService.selectOne(extendMember);
                            int newCronNum= extendMember.getCronNum()+cronNumNew;
                            extendMember.setCronNum(newCronNum);
                            tMemberService.update(extendMember);
                            //建立推广
                            TExtendPrice tdp = new TExtendPrice();
                            tdp.setCronNum(cronNumNew);
                            tdp.setMemberId(tvh.getMemberId());
                            tdp.setVipHistoryId(tvh.getId());
                            tdp.setExtendId(tex.getMemberId());
                            tdp.setPrice(tvh.getPayPrice());
                            tdp.setRechargeRate(rechargeRate);
                            tdp.setName(tex.getNickName());
                            tdp.setTel(tex.getTel());
                            tdp.setRechargeTime(new Date());
                            tExtendPriceService.update(tdp);
                        }
                    }
                }

            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return "Success";
    }





    @PostMapping("/openapi/payBack")
    public Object  payBack(ModelMap modelMap, HttpServletRequest request, @RequestBody Map<String, Object> params)
    {
        logger.info("支付宝回调参数:"+params);
        if(params != null && !"".equals(params))
        {
            if("Success".equals(params.get("status")))
            {
                String merchantOrderNo = params.get("merchant_order_no").toString();
                String tradeNo = params.get("tradeNo").toString();
                String attach = params.get("attach").toString();
                String[] sf = attach.split("ying");
                TVipHistory tvh = new TVipHistory();
                tvh.setPayNo(merchantOrderNo);
                tvh.setPayStatus(1);
                tvh = tVipHistoryService.selectOne(tvh);
                if(tvh == null ||"".equals(tvh))
                {
                    return "fail";
                }
                tvh.setPayTime(new Date());
                tvh.setPayStatus(2);
                tvh.setPayOutNo(tradeNo);
                tVipHistoryService.update(tvh);
                //更新用户VIP,及其使用期限
                TMember tmb = new TMember();
                tmb.setId(Integer.valueOf(sf[0]));
                tmb = tMemberService.selectOne(tmb);
                tmb.setIsVip(1);
                tmb.setVipId(Integer.valueOf(sf[2]));
                Date oldDay = tmb.getVipDate();
                if(oldDay == null || "".equals(oldDay))
                {
                    oldDay = new Date();
                }
                Calendar ca = Calendar.getInstance();
                ca.setTime(oldDay);
                if(Integer.valueOf(sf[3])==1)
                {
                    ca.add(Calendar.DATE, 30);
                }
                else if(Integer.valueOf(sf[3])==2)
                {
                    ca.add(Calendar.DATE, 90);;
                }
                else if(Integer.valueOf(sf[3])==3)
                {
                    ca.add(Calendar.DATE, 365);
                }
//                TVip tVip = new TVip();
//                tVip.setId(Integer.valueOf(sf[2]));
//                tVip = tVipService.selectOne(tVip);
//                tmb.setCacheNum(tVip.getCacheNum());
                Date cc = ca.getTime();
                tmb.setVipDate(cc);
                //扣除钻石数
                if(tvh.getIsUseCron() == 2)
                {
                    if(tmb.getCronNum().intValue()>tvh.getUseCron().intValue())
                    {
                        int newCrom = tmb.getCronNum()-tvh.getUseCron();
                        tmb.setCronNum(newCrom);
                    }
                }
                tMemberService.update(tmb);
                //更改充值
                //获取渠道码
                TMemberLogin ml = new TMemberLogin();
                ml.setMemberId(Integer.valueOf(sf[0]));
                ml = tMemberLoginService.selectOne(ml);
                this.getReportCache(3, ml.getFromCode(), String.valueOf(tvh.getPayPrice()));

                //进行充值分配钻石
                //获取后台比例
                Map<String,Object> tf = new HashMap<String,Object>();
                tf = tRateService.selectRate();
                if(tf != null && !"".equals(tf))
                {
                    if(tf.get("rechargeRate") != null && !"".equals(tf.get("rechargeRate")))
                    {
                        Double rechargeRate = Double.valueOf(tf.get("rechargeRate").toString());
                        Double cronNumDouble= DoubleUtil.multiplyForRoundHalfUp(tvh.getPayPrice(),rechargeRate,0);
                        int cronNumNew =cronNumDouble.intValue();
                        //获取被推广人的金币
                        TExtensionHistory tex = new TExtensionHistory();
                        tex.setExtendId(tvh.getMemberId());
                        tex=tExtensionHistoryService.selectOne(tex);
                        if(tex != null && !"".equals(tex))
                        {
                            TMember extendMember = new TMember();
                            extendMember.setId(tex.getMemberId());
                            extendMember = tMemberService.selectOne(extendMember);
                            int newCronNum= extendMember.getCronNum()+cronNumNew;
                            extendMember.setCronNum(newCronNum);
                            tMemberService.update(extendMember);
                            //建立推广
                            TExtendPrice tdp = new TExtendPrice();
                            tdp.setCronNum(cronNumNew);
                            tdp.setMemberId(tvh.getMemberId());
                            tdp.setVipHistoryId(tvh.getId());
                            tdp.setExtendId(tex.getMemberId());
                            tdp.setPrice(tvh.getPayPrice());
                            tdp.setRechargeRate(rechargeRate);
                            tdp.setName(tex.getNickName());
                            tdp.setTel(tex.getTel());
                            tdp.setRechargeTime(new Date());
                            tExtendPriceService.update(tdp);
                        }
                    }
                }

                return "success";
            }
        }
        return "fail";
    }

    /**
     * 返回的消息
     * @param modelMap
     * @param request
     * @param params
     * @return
     */

    @PostMapping("/ying/getPayStatus")
    public Object getPayStatus(ModelMap modelMap, HttpServletRequest request, @RequestBody Map<String, Object> params)
    {
        if(params == null || "".equals(params))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "充值失败,参数异常!");
            return setSuccessResponse(modelMap);
        }
        if(params.get("tradeNo") == null || "".equals(params.get("tradeNo")))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "充值失败,参数异常!");
            return setSuccessResponse(modelMap);
        }
        TVipHistory tvh = new TVipHistory();
        tvh.setPayNo(params.get("tradeNo").toString());
        tvh = tVipHistoryService.selectOne(tvh);

        if(tvh == null || "".equals(tvh))
        {
            modelMap.put("retCode", "-1");
            modelMap.put("retMsg", "支付宝充值!");
            return setSuccessResponse(modelMap);
        }
        if(tvh.getPayStatus().intValue()==2)
        {
            modelMap.put("retCode", "1");
            modelMap.put("retMsg", "充值成功!");
            return setSuccessResponse(modelMap);
        }
        modelMap.put("retCode", "-1");
        modelMap.put("retMsg", "充值暂未成功!");
        return setSuccessResponse(modelMap);

    }




    public static String createSign(Map<String, String> params, String partnerKey) {
        // 生成签名前先去除sign
        String stringA = packageSign(params, false);
        String stringSignTemp = stringA + "&key=" + partnerKey;
        return HashUtil.md5(stringSignTemp);
    }

    /**
     * 组装签名的字段
     *
     * @param params
     *            参数
     * @param urlEncoder
     *            是否urlEncoder
     * @return String
     */
    public static String packageSign(Map<String, String> params, boolean urlEncoder) {
        // 先将参数以其参数名的字典序升序进行排序
        TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
        // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Entry<String, String> param : sortedParams.entrySet()) {
            String value = param.getValue();
            if (StringUtils.isBlank(value)) {
                continue;
            }
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }
            sb.append(param.getKey()).append("=");
            if (urlEncoder) {
                try {
                    value = urlEncode(value);
                } catch (UnsupportedEncodingException e) {
                }
            }
            sb.append(value);
        }
        return sb.toString();
    }

    /* urlEncode
     *
     * @param src
     *            微信参数
     * @return String
     * @throws UnsupportedEncodingException
     *             编码错误
     */
    public static String urlEncode(String src) throws UnsupportedEncodingException {
        return URLEncoder.encode(src, Charsets.UTF_8.name()).replace("+", "%20");
    }
}