package org.springblade.third.auth.controller;

import com.alibaba.fastjson.JSONObject;
import com.xkcoding.http.util.MapUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springblade.core.tool.api.R;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.third.auth.constants.CtwingAuthConstants;
import org.springblade.third.auth.entity.AccountOauth;
import org.springblade.third.auth.service.IAccountOauthService;
import org.springblade.third.auth.util.AuthRequestUtil;
import org.springblade.third.auth.util.ByteFormat;
import org.springblade.third.auth.util.XXTeaUtil;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @description:
 * @author:xuanyan
 * @create: 2022-09-29 09:57
 **/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("ctwing/login")
public class CtwingController {

	private IAccountOauthService accountOauthService;
	private IUserService userService;

	@RequestMapping(value = "/render/{source}")
	@ResponseBody
	public R renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
		log.warn("进入render：" + source);
		AuthRequest authRequest = AuthRequestUtil.getAuthRequest(source);
		String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
		log.warn(authorizeUrl);
		return R.data(authorizeUrl);
	}

	@RequestMapping("/callBack/{source}")
	public R ctwingCallBack(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request){
		AuthRequest authRequest = AuthRequestUtil.getAuthRequest(source);
		callback = this.getAuthCallback(source, callback, request);
		AuthResponse<AuthUser> response = authRequest.login(callback);
		log.warn(JSONObject.toJSONString(response));

		if (response.ok()) {
			AuthUser data = response.getData();
			String uuid = data.getUuid();
			String mobile = data.getUsername();
			String avatar = data.getAvatar();
			AccountOauth dbAccount = accountOauthService.lambdaQuery().eq(AccountOauth::getUuid,uuid).eq(AccountOauth::getSource,source).one();
			User dbUser = userService.lambdaQuery().eq(User::getPhone,mobile).one();
			if (dbAccount == null){
				if (dbUser == null){
					return R.data("该用户不存在");
				}else {
					AccountOauth accountOauth = new AccountOauth();
					accountOauth.setUuid(uuid);
					accountOauth.setAccountId(dbUser.getId());
					accountOauth.setUserName(mobile);
					accountOauth.setNickName(dbUser.getAccount());
					accountOauth.setAvatar(avatar);
					accountOauth.setEmail(dbUser.getEmail());
					accountOauth.setSource(source);
					Boolean saveAccount = accountOauthService.save(accountOauth);
					return R.data(saveAccount);
				}
			}else {
				if (dbUser == null){
					return R.data("该用户不存在");
				}else {
					Boolean updateAccount = accountOauthService.lambdaUpdate()
						.eq(AccountOauth::getId,dbAccount.getId())
						.set(AccountOauth::getUserName,mobile)
						.set(AccountOauth::getNickName,dbUser.getAccount())
						.set(AccountOauth::getAvatar,avatar)
						.set(AccountOauth::getEmail,dbUser.getEmail()).update();
					return R.data(updateAccount);
				}
			}
		}
		return R.data("请求第三方接口失败");
	}

	private AuthCallback getAuthCallback(String source, AuthCallback authCallback, HttpServletRequest request){
		if("ctwing".equals(source)){
			String paras = request.getParameter("paras");
			try {
				// XXTea解密非公共加密参数
				String decValue = new String(XXTeaUtil.decrypt(ByteFormat.hexToBytes(paras), CtwingAuthConstants.APP_SECRET.getBytes(CtwingAuthConstants.DEFAULT_CHARSET)));
				Map<String, String> resultMap = MapUtil.parseStringToMap(decValue, false);
				if(0 == Integer.valueOf(resultMap.get("result"))){
					authCallback.setCode(resultMap.get("code"));
					authCallback.setState(resultMap.get("state"));
				}
				log.warn(decValue);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return authCallback;
	}

}
