package com.liquidnet.service.adam.controller;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileRequest;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
import com.aliyuncs.exceptions.ClientException;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.core.JwtValidator;
import com.liquidnet.service.ResponseDto;
import com.liquidnet.service.adam.dto.AdamThirdPartParam;
import com.liquidnet.service.adam.dto.vo.AdamLoginInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamThirdPartInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.service.IAdamRealNameService;
import com.liquidnet.service.adam.service.IAdamThirdPartyService;
import com.liquidnet.service.adam.service.IAdamUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
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.core.env.Environment;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@ApiSupport(order = 10010)
@Api(tags = "用户登录")
@Slf4j
@RestController
@RequestMapping("")
public class AdamLoginController {
    @Autowired
    Environment environment;
    @Autowired
    JwtValidator jwtValidator;
    @Autowired
    DefaultAcsClient defaultAcsClient;
    @Autowired
    IAdamUserService adamUserService;
    @Autowired
    IAdamRealNameService adamRealNameService;
    @Autowired
    IAdamThirdPartyService adamThirdPartyService;

    /*@ApiOperationSupport(order = 1)
    @ApiOperation(value = "手机号密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", dataType = "String", name = "password", value = "密码"),
    })
    @PostMapping(value = {""})
    public ResponseDto<AdamLoginInfoVo> loginByPwd(@RequestParam String mobile, @RequestParam String password) {
        log.info("mobile:{},pwd:{}", mobile, password);
        DigestUtils.md5DigestAsHex((password + "salt_").getBytes(StandardCharsets.UTF_8));


        return ResponseDto.success(AdamLoginInfoVo.getNew());
    }*/

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
    })
    @GetMapping(value = {"send"})
    public ResponseDto<Object> sendSms(@RequestParam String mobile) {
        log.info("send to mobile:{}", mobile);

        LinkedMultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
        paramsMap.add("mobile", mobile);
        LinkedMultiValueMap<String, String> headersMap = new LinkedMultiValueMap<>();
        headersMap.add("token", null);

        try {
            // TODO: 2021/5/12
            String respStr = HttpUtil.post("https://service.zhengzai.tv/smsCode", paramsMap, headersMap);
            log.info("###PHP.API[{}].RESP[{}]", "https://service.zhengzai.tv/smsCode", respStr);

//            Map respMap = JsonUtils.fromJson(respStr, Map.class);

        } catch (Exception e) {
            log.error("验证码发送异常[mobile:{}]", mobile, e);
            return ResponseDto.failure("验证码发送失败");
        }
        return ResponseDto.success();
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "手机号验证码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "code", value = "验证码"),
    })
    @PostMapping(value = {"login/sms"})
    public ResponseDto<AdamLoginInfoVo> loginBySms(@RequestParam String mobile, @RequestParam String code) {
        // TODO: 2021/5/12 参数检验
        log.info("mobile:{},pwd:{}", mobile, code);

        if (!this.checkSmsCode(mobile, code)) return ResponseDto.failure("验证码无效");

        String uid = adamUserService.queryUidByRedis(mobile);
        AdamUserInfoVo userInfoVo =
                StringUtils.isEmpty(uid) ? adamUserService.register(mobile) : adamUserService.queryByUid(uid);
        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        if (userInfoVo.getIsComplete() == 1) {
            loginInfoVo.setRealNameInfo(adamRealNameService.queryByUid(userInfoVo.getUid()));
            loginInfoVo.setThirdPartInfo(adamThirdPartyService.queryByUid(userInfoVo.getUid()));
            // TODO: 2021/5/12 会员信息
            loginInfoVo.setMemberInfo(null);
        }
        loginInfoVo.setUserInfo(userInfoVo);

        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put("uid", userInfoVo.getUid());
        loginInfoVo.setToken(jwtValidator.create(claimsMap));

        return ResponseDto.success(loginInfoVo);
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "手机号一键登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "accessToken", value = "访问令牌"),
    })
    @PostMapping(value = {"login/mobile"})
    public ResponseDto<AdamLoginInfoVo> loginByMobile(@RequestParam String accessToken) {
        // TODO: 2021/5/10
        log.info("login by mobile access token:{}", accessToken);

        String mobile = this.getMobile(accessToken);
        if (StringUtils.isEmpty(mobile)) return ResponseDto.failure("手机号获取失败，请更换登录方式");

        String uid = adamUserService.queryUidByRedis(mobile);
        AdamUserInfoVo userInfoVo =
                StringUtils.isEmpty(uid) ? adamUserService.register(mobile) : adamUserService.queryByUid(uid);
        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        if (loginInfoVo.getUserInfo().getIsComplete() == 1) {
            loginInfoVo.setRealNameInfo(adamRealNameService.queryByUid(userInfoVo.getUid()));
            loginInfoVo.setThirdPartInfo(adamThirdPartyService.queryByUid(userInfoVo.getUid()));
            // TODO: 2021/5/12 会员信息
            loginInfoVo.setMemberInfo(null);
        }
        loginInfoVo.setUserInfo(userInfoVo);

        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put("uid", userInfoVo.getUid());
        loginInfoVo.setToken(jwtValidator.create(claimsMap));

        return ResponseDto.success(AdamLoginInfoVo.getNew());
    }

//    @ApiOperationSupport(order = 5)
//    @ApiOperation(value = "第三方账号注册")
//    @ApiImplicitParams({
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "openId", value = "第三方OPENID"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "nickname", value = "昵称"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "avatar", value = "头像"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "platform", value = "平台类型", allowableValues = "WEIBO,WECHAT,QQ"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "platform", value = "验证码"),
//    })
//    @PostMapping(value = {"tpa/reg"})
//    public ResponseDto<AdamLoginInfoVo> loginByTpaRegister(@RequestParam String openId, @RequestParam String nickname,
//                                                           @RequestParam String avatar, @RequestParam String platform,
//                                                           @RequestParam String mobile, @RequestParam String code) {
//        log.info("login by tpa openId:{},nickname:{},avatar:{},platform:{},mobile:{},code:{}",
//                openId, nickname, avatar, platform, mobile, code);
//
//        // TODO: 2021/5/10
//
//
//        return ResponseDto.success(AdamLoginInfoVo.getNew());
//    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "第三方账号登录")
    @PostMapping(value = {"login/tpa"})
    public ResponseDto<AdamLoginInfoVo> loginByTpa(@RequestBody AdamThirdPartParam parameter) {
        // TODO: 2021/5/10
        log.info("login by tpa:{}", JsonUtils.toJson(parameter));

        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        if (StringUtils.isEmpty(parameter.getMobile())) {
            AdamThirdPartInfoVo thirdPartInfoVo = adamThirdPartyService.queryByOpenId(parameter.getOpenId(), parameter.getPlatform());
            if (Objects.isNull(thirdPartInfoVo)) return ResponseDto.failure("第三方账号未注册");

            loginInfoVo.setUserInfo(adamUserService.queryByUid(thirdPartInfoVo.getUid()));
            loginInfoVo.setRealNameInfo(adamRealNameService.queryByUid(thirdPartInfoVo.getUid()));
            loginInfoVo.setThirdPartInfo(adamThirdPartyService.queryByUid(thirdPartInfoVo.getUid()));
        } else {// 新账号注册
            if (!this.checkSmsCode(parameter.getMobile(), parameter.getCode())) return ResponseDto.failure("验证码无效");

            loginInfoVo.setUserInfo(adamUserService.register(parameter));
        }

        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put("uid", loginInfoVo.getUserInfo().getUid());
        loginInfoVo.setToken(jwtValidator.create(claimsMap));

        return ResponseDto.success(loginInfoVo);
    }

    /* ---------------------------- Internal Method ---------------------------- */

    private boolean checkSmsCode(String mobile, String code) {
        if ("dev".equals(environment.getProperty("spring.profiles.active")) && "111111".equals(code)) {
            return true;
        }

        LinkedMultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
        paramsMap.add("mobile", mobile);
        paramsMap.add("code", code);
        LinkedMultiValueMap<String, String> headersMap = new LinkedMultiValueMap<>();
        headersMap.add("token", null);

        try {
            // TODO: 2021/5/12
            String respStr = HttpUtil.get("https://service.zhengzai.tv/smsValidation", paramsMap, headersMap);
            log.info("###PHP.API.RESP:{}", respStr);

            Map respMap = JsonUtils.fromJson(respStr, Map.class);

            return StringUtils.equalsIgnoreCase("OK", (String) respMap.get("message"));
        } catch (Exception e) {
            log.error("验证码验证异常[mobile:{},code:{}]", mobile, code, e);
            return false;
        }
    }

    private String getMobile(String accessToken) {
        try {
            GetMobileRequest request = new GetMobileRequest();
            request.setAccessToken(accessToken);

            GetMobileResponse response = defaultAcsClient.getAcsResponse(request);

            if (!Objects.isNull(response) && response.getCode().equalsIgnoreCase("OK")) {
                return response.getGetMobileResultDTO().getMobile();
            }
        } catch (ClientException e) {
            log.error("error:aliyun.dypns.api:{}", accessToken, e);
        }
        return null;
    }
}
