package com.gxwebsoft.open.controller;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CacheClient;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.WxOfficialUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.LoginRecord;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.param.UserParam;
import com.gxwebsoft.common.system.service.LoginRecordService;
import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.oa.service.NoticeService;
import com.gxwebsoft.shop.entity.UserOauth;
import com.gxwebsoft.shop.param.UserOauthParam;
import com.gxwebsoft.shop.service.UserOauthService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;

import static com.gxwebsoft.common.core.utils.CommonUtil.randomUsername;

/**
 * 微信公众号接口
 *
 * @author WebSoft
 * @since 2022-11-19 13:54:27
 */
@Api(tags = "微信公众号授权登录")
@RestController
@RequestMapping("/api/open/wx-official")
public class OpenWxOfficialController extends BaseController {
    @Resource
    private ConfigProperties configProperties;
    @Resource
    private WxOfficialUtil wxOfficialUtil;
    @Resource
    private UserService userService;
    @Resource
    private UserOauthService userOauthService;
    @Resource
    private LoginRecordService loginRecordService;
    @Resource
    private SettingService settingService;

  public OpenWxOfficialController() {
  }

  @OperationLog
    @ApiOperation("第一步：用户同意授权，获取code")
    @GetMapping("/code")
    public ApiResult<?> code() throws UnsupportedEncodingException {
      WxOfficialUtil client = wxOfficialUtil.client(getTenantId());
      String codeUrl = client.getCodeUrl();
      return success(codeUrl);
    }

    @OperationLog
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("第二步：通过code换取网页授权access_token")
    @GetMapping("/accessToken")
    public String accessToken(String code, String state, HttpServletRequest request, HttpServletResponse resp) throws IOException {
      if(StrUtil.equals(state,"STATE")){
        throw new BusinessException("租户ID不正确");
      }

      // 1.实例化
      WxOfficialUtil client = wxOfficialUtil.client(Integer.valueOf(state));

      // 2.获取access_token
      final String access_token = client.getAccessToken(code);

      // 准备数据
      final String unionid = client.unionid;
      final String expires_in = client.expires_in;
      final JSONObject cache = settingService.getCache("cache".concat(state).concat(":setting:setting"));
      final String domain = "https://" + cache.getString("domain");

      // 3.查询第三方用户信息表
      UserOauthParam userOauthParam = new UserOauthParam();
      userOauthParam.setUnionid(unionid);
      userOauthParam.setTenantId(Integer.valueOf(state));
      System.out.println("userOauthParam = " + userOauthParam);
      final UserOauth oauthUser = userOauthService.getByUnionId(userOauthParam);
      System.out.println("oauthUser = " + oauthUser);

      // 4.1存在签发token
      if(oauthUser != null){
        UserParam userParam = new UserParam();
        userParam.setUserId(oauthUser.getUserId());
        userParam.setTenantId(Integer.valueOf(state));
        System.out.println("userParam = " + userParam);
        User user = userService.getByUnionId(userParam);
        // 5.签发token
        System.out.println("user = 签发token " + user);
        String wx_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), Integer.valueOf(state)),
          configProperties.getTokenExpireTime(), configProperties.getTokenKey());
        resp.sendRedirect(domain + "/passport/wx-official-login?token=".concat(wx_token).concat("&username=").concat(user.getUsername()));
        return "登录成功";
      }
      // 4.2不存在则注册并登录签发token
      final JSONObject userInfo = client.getUserInfo(access_token);
      final String openid = userInfo.getString("openid");
      final String unionId = userInfo.getString("unionid");
      final String nickname = userInfo.getString("nickname");
      final String sex = userInfo.getString("sex");
      final String province = userInfo.getString("province");
      final String city = userInfo.getString("city");
      final String country = userInfo.getString("country");
      final String headimgurl = userInfo.getString("headimgurl");
      System.out.println("headimgurl = " + headimgurl);
      System.out.println("unionId = " + unionId);
      System.out.println("openid = " + openid);
      System.out.println("nickname = " + nickname);
      User user = new User();
      user.setNickname(nickname);
      user.setType(0);
      user.setUsername(randomUsername("wx_"));
      user.setPassword(userService.encodePassword(CommonUtil.randomUUID16()));
      user.setSex(sex);
      user.setPlatform("WX-OFFICIAL");
      user.setProvince(province);
      user.setCity(city);
      user.setCountry(country);
      user.setAvatar(headimgurl);
      user.setTenantId(Integer.valueOf(state));
      userService.saveUser(user);
      System.out.println("userLast = " + user);
      UserOauth userOauth = new UserOauth();
      userOauth.setTenantId(Integer.valueOf(state));
      userOauth.setOauthType("WX-OFFICIAL");
      userOauth.setOauthId(openid);
      userOauth.setUnionid(unionId);
      userOauth.setUserId(user.getUserId());
      userOauthService.save(userOauth);
      loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_LOGIN, null, Integer.valueOf(state), request);
      // 5.签发token
      String wx_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), Integer.valueOf(state)),
        configProperties.getTokenExpireTime(), configProperties.getTokenKey());
      resp.sendRedirect(domain + "/passport/wx-official-login?token=".concat(wx_token).concat("&username=").concat(user.getUsername()));
      return "注册成功";
    }
}
