package org.springblade.modules.auth.endpoint;

import com.wf.captcha.SpecCaptcha;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.time.Duration;
import java.util.UUID;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.jwt.JwtUtil;
import org.springblade.core.jwt.props.JwtProperties;
import org.springblade.core.oauth2.granter.TokenGranter;
import org.springblade.core.oauth2.granter.TokenGranterFactory;
import org.springblade.core.oauth2.handler.AuthorizationHandler;
import org.springblade.core.oauth2.handler.TokenHandler;
import org.springblade.core.oauth2.provider.OAuth2Request;
import org.springblade.core.oauth2.provider.OAuth2Token;
import org.springblade.core.oauth2.provider.OAuth2Validation;
import org.springblade.core.oauth2.service.OAuth2User;
import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.modules.system.mapper.UserMapper;
import org.springblade.modules.system.pojo.entity.User;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Tag(
	name = "用户授权认证",
	description = "1 - OAuth2授权认证端点"
)
public class MiniAppOauth2EndPoint {
	private final BladeRedis bladeRedis;
	private final JwtProperties jwtProperties;
	private final TokenGranterFactory granterFactory;
	private final AuthorizationHandler authorizationHandler;
	private final TokenHandler tokenHandler;
	private final UserMapper userMapper;

	@PostMapping({"/oauth/miniapp/token"})
	@Operation(
		summary = "获取Token",
		description = "OAuth2认证接口",
		parameters = {@Parameter(
			in = ParameterIn.QUERY,
			name = "username",
			description = "账号",
			schema = @Schema(
				type = "string"
			)
		), @Parameter(
			in = ParameterIn.QUERY,
			name = "password",
			description = "密码",
			schema = @Schema(
				type = "string"
			)
		), @Parameter(
			in = ParameterIn.QUERY,
			name = "grant_type",
			description = "授权类型",
			schema = @Schema(
				type = "string"
			)
		), @Parameter(
			in = ParameterIn.QUERY,
			name = "refresh_token",
			description = "刷新token",
			schema = @Schema(
				type = "string"
			)
		), @Parameter(
			in = ParameterIn.QUERY,
			name = "scope",
			description = "权限范围",
			schema = @Schema(
				type = "string"
			)
		)}
	)
	public R token() {
		try{
			OAuth2Request request = OAuth2Request.create().buildArgs();
			TokenGranter tokenGranter = this.granterFactory.create(request.getGrantType());
			OAuth2User user = tokenGranter.user(request);
			if(!"6".equals(user.getDeptId()) && !"roleAll".equals(user.getAccount())){
				throw new IllegalArgumentException("当前账号无权限登录");
			}
			User us = userMapper.findUserById(Long.parseLong(user.getUserId()));
			if(us.getStatus() != 0){
				throw new IllegalArgumentException("当前账号无权限登录");
			}
			OAuth2Validation validation = this.authorizationHandler.authValidation(user, request);
			if (!validation.isSuccess()) {
				this.authorizationHandler.authFailure(user, request, validation);
				OAuth2ExceptionUtil.throwFromCode(validation.getCode());
			}

			OAuth2Token token = tokenGranter.token(user, request);
			OAuth2Token enhanceToken = this.tokenHandler.enhance(user, token, request);
			this.authorizationHandler.authSuccessful(user, request);
			return R.data(enhanceToken.getArgs());
		}catch (Exception e){
			return R.fail(e.getMessage());
		}

	}

	@GetMapping({"/oauth/miniapp/logout"})
	@Operation(
		summary = "退出登录"
	)
	public Kv logout() {
		BladeUser user = AuthUtil.getUser();
		if (user != null && this.jwtProperties.getState()) {
			OAuth2Request request = OAuth2Request.create().buildHeaderArgs();
			String token = JwtUtil.getToken(request.getToken());
			JwtUtil.removeAccessToken(user.getTenantId(), user.getClientId(), String.valueOf(user.getUserId()), token);
		}

		return Kv.create().set("success", "true").set("msg", "success");
	}

	@GetMapping({"/oauth/miniapp/captcha"})
	@Operation(
		summary = "获取验证码"
	)
	public Kv captcha() {
		SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
		String verCode = specCaptcha.text().toLowerCase();
		String key = UUID.randomUUID().toString();
		this.bladeRedis.setEx("blade:auth::blade:captcha:" + key, verCode, Duration.ofMinutes(30L));
		return Kv.create().set("key", key).set("image", specCaptcha.toBase64());
	}

	@GetMapping({"/oauth/miniapp/clear-cache"})
	@Operation(
		summary = "清除缓存"
	)
	public Kv clearCache() {
		CacheUtil.clear("blade:biz");
		CacheUtil.clear("blade:user");
		CacheUtil.clear("blade:dict");
		CacheUtil.clear("blade:flow");
		CacheUtil.clear("blade:sys");
		CacheUtil.clear("blade:param");
		CacheUtil.clear("blade:resource");
		CacheUtil.clear("blade:menu");
		CacheUtil.clear("blade:dict", Boolean.FALSE);
		CacheUtil.clear("blade:menu", Boolean.FALSE);
		CacheUtil.clear("blade:sys", Boolean.FALSE);
		CacheUtil.clear("blade:param", Boolean.FALSE);
		return Kv.create().set("success", "true").set("msg", "success");
	}

	public MiniAppOauth2EndPoint(final BladeRedis bladeRedis, final JwtProperties jwtProperties, final TokenGranterFactory granterFactory, final AuthorizationHandler authorizationHandler, final TokenHandler tokenHandler, UserMapper userMapper) {
		this.bladeRedis = bladeRedis;
		this.jwtProperties = jwtProperties;
		this.granterFactory = granterFactory;
		this.authorizationHandler = authorizationHandler;
		this.tokenHandler = tokenHandler;
        this.userMapper = userMapper;
    }
}
