package com.xhpc.user.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.xhpc.common.api.SettingConfigService;
import com.xhpc.common.core.constant.HttpStatus;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.core.utils.HttpUtils;
import com.xhpc.common.core.utils.StringUtils;
import com.xhpc.common.core.utils.sign.Base64;
import com.xhpc.common.core.web.controller.BaseController;
import com.xhpc.common.core.web.domain.AjaxResult;
import com.xhpc.common.core.web.page.TableDataInfo;
import com.xhpc.common.log.annotation.Log;
import com.xhpc.common.log.enums.BusinessType;
import com.xhpc.user.service.IXhpcAppUserUserService;
import io.swagger.annotations.ApiOperation;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * C端用户
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/app/user")
public class XhpcAppUserController extends BaseController {

    @Autowired
    private IXhpcAppUserUserService iXhpcAppUserUserService;

    @Autowired
    private SettingConfigService settingConfigService;

    @Autowired
    private Environment environment;
    /**
     * C端用户详情
     */
    @ApiOperation("C端用户详情")
    //@PreAuthorize(hasPermi = "app:user:info")
    @GetMapping("/info")
    public AjaxResult info(@RequestParam Long appUserId) {
        return AjaxResult.success(iXhpcAppUserUserService.info(appUserId));
    }

    /**
     * C端用户分页列表
     */
    //@PreAuthorize(hasPermi = "app:user:page")
    @GetMapping("/page")
    public TableDataInfo page(HttpServletRequest request,String phone) {
        List<Map<String, Object>> list = iXhpcAppUserUserService.selectAppUserList(request,phone);
        return getDataTable(list);
    }

    /**
     * 禁用/启用C端用户
     */
    @Log(title = "C端用户--（禁用/启用）", businessType = BusinessType.UPDATE)
    @ApiOperation("禁用/启用C端用户")
    //@PreAuthorize(hasPermi = "app:user:status")
    @PostMapping("/status")
    public AjaxResult status(@RequestBody Map<String, Object> map) {
        String appUserId = StringUtils.valueOf(map.get("appUserId"));
        if (StringUtils.isEmpty(appUserId)) {
            return AjaxResult.error(HttpStatus.NOT_NULL, "C端用户信息不能为空");
        }
        iXhpcAppUserUserService.status(Long.parseLong(appUserId));
        return AjaxResult.success();
    }

    /**
     * 统计
     * @param phone
     * @return
     */
    @GetMapping("/userSum")
    public AjaxResult userSum(String phone) {
        return AjaxResult.success(iXhpcAppUserUserService.userSum(phone));
    }



    /**
     * 以下为小程序接口
     */

    /**
     * C端用户注册
     */
    //@Log(title = "C端用户--注册", businessType = BusinessType.INSERT)
    @ApiOperation("注册")
    @PostMapping("/register")
    public R<?> register(@RequestBody Map<String, Object> map) {
        return iXhpcAppUserUserService.register(map);
    }

    /**
     * C端用户登录
     */
    @ApiOperation("登录")
    @PostMapping("/login")
    public R<?> login(@RequestBody Map<String, Object> map) {
        return iXhpcAppUserUserService.login(map);
    }

    /**
     * 小程序用户详情
     */
    @ApiOperation("小程序用户详情")
    @GetMapping("/appInfo")
    public AjaxResult appInfo(HttpServletRequest request) {
        return iXhpcAppUserUserService.appInfo(request);
    }

    /**
     * 小程序用户退出
     */
    @ApiOperation("小程序用户退出")
    @PostMapping("/loginOut")
    public R<?> loginOut(HttpServletRequest request, @RequestParam String type) {
        return iXhpcAppUserUserService.loginOut(request, type);
    }

    /**
     * C端用户自动登录
     */
    @ApiOperation("C端用户自动登录")
    @PostMapping("/voluntaryLogin")
    public R<?> voluntaryLogin(@RequestBody Map<String, Object> map) {
        return iXhpcAppUserUserService.voluntaryLogin(map);
    }

    /*
     * TODO 获取微信权限标识 openid ,session_key,unionid
     * @author fjd
     * @date 2020-06-24 10:07
     */
    @PostMapping("/jscode2session")
    @ApiOperation(value = "获取微信权限标识", notes = "jsCode")
    public R<?> jsCode(String jsCode, String encryptedData, String iv,String tenantId) {
        if (StringUtils.isEmpty(jsCode)) {
            return R.fail(HttpStatus.NOT_NULL, "信息不完整");
        }
        encryptedData =encryptedData.replace(' ','+');
        if("".equals(tenantId) || null==tenantId){
            tenantId="000000";
        }
        R r = settingConfigService.settingConfig(1, tenantId);
        if(r !=null && r.getCode()==200){
            Map<String, Object> mapConfig = (Map<String, Object>)r.getData();
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+mapConfig.get("wxAppId").toString()+"&secret="+mapConfig.get("wxAppSecret").toString()+"&js_code="+ jsCode + "&grant_type=authorization_code";
            String result = HttpUtils.get(url);
            JSONObject json = JSON.parseObject(result);
            if (null != json) {
                String openid = json.getString("openid");
                String sessionKey = json.getString("session_key");
                System.out.println("sessionKey:"+sessionKey);
                if (StringUtils.isEmpty(openid)) {
                    return R.fail(HttpStatus.ERROR_STATUS, "openid获取失败");
                }
                if (StringUtils.isEmpty(sessionKey)) {
                    return R.fail(HttpStatus.ERROR_STATUS, "openid获取失败");
                }
                Map<String, Object> map = new HashMap<>(16);
                map.put("openid", openid);
                JSONObject jsonObject = new JSONObject();
                if ((!"".equals(encryptedData) && encryptedData != null) && (!"".equals(iv) && iv != null)) {
                    jsonObject = getPhoneNumber(encryptedData, sessionKey, iv);
                    if (jsonObject !=null) {
                        map.put("name", jsonObject.get("nickName"));
                        map.put("sex", jsonObject.get("gender"));
                        map.put("avatar", jsonObject.get("avatarUrl"));
                        map.put("phone", jsonObject.get("purePhoneNumber"));
                    }
                }
                return R.ok(map);
            }
        }


        return R.fail(HttpStatus.ERROR_STATUS, "openid获取失败");
    }

    /*
     * TODO 微信获取手机号
     * @author fjd
     * @date 2020-06-24 11:23
     */
    public JSONObject getPhoneNumber(String encryptedData, String sessionKey, String iv) {
        try {
            // 被加密的数据
            byte[] dataByte = Base64.decode(encryptedData);
            // 加密秘钥
            byte[] keyByte = Base64.decode(sessionKey);
            // 偏移量
            byte[] ivByte = Base64.decode(iv);
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 支付宝授权
     */
    @ApiOperation("支付宝授权")
    @PostMapping("/alipayEmpower")
    public AjaxResult alipayEmpower(@RequestParam String code,String tenantId) throws Exception {
        if("".equals(tenantId) || null==tenantId){
            tenantId="000000";
        }
        R r = settingConfigService.settingConfig(2, tenantId);
        if(r !=null && r.getCode()==200){
            Map<String, Object> map = (Map<String, Object>)r.getData();
            /** 初始化 **/
            CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
            /** 支付宝网关 **/
            certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
            /** 应用id，如何获取请参考：https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
            certAlipayRequest.setAppId(map.get("zfbAppId").toString());
            /** 应用私钥, 如何获取请参考：https://opensupport.alipay.com/support/helpcenter/207/201602471154?ant_source=antsupport  **/
            certAlipayRequest.setPrivateKey(map.get("zfbPrivateKey").toString());
            /** 应用公钥证书路径，下载后保存位置的绝对路径  **/
            certAlipayRequest.setCertPath(map.get("zfbAppCertPublicKey").toString());
            /** 支付宝公钥证书路径，下载后保存位置的绝对路径 **/
            certAlipayRequest.setAlipayPublicCertPath(map.get("zfbAlipayCertPublicKeyRsa").toString());
            /** 支付宝根证书路径，下载后保存位置的绝对路径 **/
            certAlipayRequest.setRootCertPath(map.get("zfbAlipayRootCert").toString());
            /** 设置签名类型 **/
            certAlipayRequest.setSignType("RSA2");
            /** 设置请求格式，固定值json **/
            certAlipayRequest.setFormat("json");
            /** 设置编码格式 **/
            certAlipayRequest.setCharset("UTF-8");
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setGrantType("authorization_code");
            //  auth_code  前端授权后得到的授权码
            request.setCode(code);
            AlipaySystemOauthTokenResponse response = alipayClient.certificateExecute(request);
            //服务端请求返回，RSA2密钥和公钥证书请求方式不同，如当面付
            // RSA2密钥请求response = alipayClient.execute(request);
            // 公钥证书请求请求response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                System.out.println("调用成功");
            } else {
               return AjaxResult.error("获取失败");
            }
            return AjaxResult.success(response);
        }
        return AjaxResult.error("获取失败");
    }

    /**
     * 支付宝授权
     */
    @ApiOperation("支付宝授权")
    @PostMapping("/alipayEmpowerYu")
    public AjaxResult alipayEmpowerYu(@RequestParam String code) throws Exception {

        /** 初始化 **/
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        /** 支付宝网关 **/
        certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
        /** 应用id，如何获取请参考：https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
        certAlipayRequest.setAppId(environment.getProperty("ALIPAYAPPID"));
        /** 应用私钥, 如何获取请参考：https://opensupport.alipay.com/support/helpcenter/207/201602471154?ant_source=antsupport  **/
        certAlipayRequest.setPrivateKey(environment.getProperty("ALIPAYPRIVATEKEY"));
        /** 应用公钥证书路径，下载后保存位置的绝对路径  **/
        certAlipayRequest.setCertPath(environment.getProperty("CERTPATH"));
        /** 支付宝公钥证书路径，下载后保存位置的绝对路径 **/
        certAlipayRequest.setAlipayPublicCertPath(environment.getProperty("PUBLICCERTPATH"));
        /** 支付宝根证书路径，下载后保存位置的绝对路径 **/
        certAlipayRequest.setRootCertPath(environment.getProperty("ROOTCRETPATH"));
        /** 设置签名类型 **/
        certAlipayRequest.setSignType("RSA2");
        /** 设置请求格式，固定值json **/
        certAlipayRequest.setFormat("json");
        /** 设置编码格式 **/
        certAlipayRequest.setCharset("UTF-8");
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        //  auth_code  前端授权后得到的授权码
        request.setCode(code);
        AlipaySystemOauthTokenResponse response = alipayClient.certificateExecute(request);
        //服务端请求返回，RSA2密钥和公钥证书请求方式不同，如当面付
        // RSA2密钥请求response = alipayClient.execute(request);
        // 公钥证书请求请求response = alipayClient.certificateExecute(request);
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
        return AjaxResult.success(response);
    }


    /**
     * 注销账号
     */
    @ApiOperation("注销账号")
    @PostMapping("/logout")
    public R<?> logout(HttpServletRequest request,String phone, String code) {
        return iXhpcAppUserUserService.logout(request,phone, code);
    }


    /**
     * 设置小程序用户自动退款功能
     * @param
     */
    @ApiOperation("设置小程序用户自动退款功能")
    @PostMapping("/updateIsRefund")
    public R<?> updateIsRefund(@RequestBody Map<String, Object> map) {
        if(map !=null){
            Long userId = Long.parseLong(map.get("userId").toString());
            Integer userType = Integer.parseInt(map.get("userType").toString());
            Integer isRefund = Integer.parseInt(map.get("isRefund").toString());
            return iXhpcAppUserUserService.updateIsRefund(userId,userType,isRefund);
        }
        return R.fail(HttpStatus.ERROR_STATUS, "修改失败");
    }

    /**
     * 设置小程序用户电池保护
     * @param
     */
    @ApiOperation("设置小程序用户电池保护")
    @PostMapping("/batteryProtect")
    public R<?> batteryProtect(HttpServletRequest request,@RequestBody Map<String, Object> map) {
        if(map !=null){
            Integer soc = Integer.parseInt(map.get("soc").toString());
            Integer socProtect = Integer.parseInt(map.get("socProtect").toString());
            Integer userType = Integer.parseInt(map.get("userType").toString());
            return iXhpcAppUserUserService.batteryProtect(request,soc,socProtect,userType);
        }
        return R.fail(HttpStatus.ERROR_STATUS, "修改失败");
    }


}
