package com.agileboot.auth.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.auth.pojo.dto.LoginBody;
import com.agileboot.auth.pojo.dto.RegisterBody;
import com.agileboot.auth.pojo.vo.ConfigVO;
import com.agileboot.auth.pojo.vo.LoginVO;
import com.agileboot.auth.service.IAuthStrategy;
import com.agileboot.auth.service.SysLoginService;
import com.agileboot.common.core.constant.Constants;
import com.agileboot.common.core.core.R;
import com.agileboot.common.core.enums.dictionary.DictCache;
import com.agileboot.common.core.utils.ValidatorUtils;
import com.agileboot.common.satoken.pojo.LoginUser;
import com.agileboot.common.satoken.utils.LoginHelper;
import com.agileboot.system.client.service.ISysClientService;
import com.agileboot.system.client.vo.SysClientVO;
import com.agileboot.system.menu.service.ISysMenuService;
import com.agileboot.system.menu.vo.RouterVO;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 认证
 *
 * @author Lion Li
 */
@Slf4j
@SaIgnore
@RequiredArgsConstructor
@RestController
@RequestMapping("/auth")
public class AuthController {

    private final SysLoginService loginService;
    private final ISysClientService sysClientService;
    private final ISysMenuService sysMenuService;

    /**
     * 登录方法
     *
     * @param body 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public R<?> login(@RequestBody String body) {
        LoginBody loginBody = JSONObject.parseObject(body, LoginBody.class);
        ValidatorUtils.validate(loginBody);
        Long clientId = Long.parseLong(loginBody.getClientId());
        String grantType = loginBody.getGrantType();
        SysClientVO clientVo = sysClientService.queryByClientId(clientId);

        if (ObjectUtil.isNull(clientVo) || !StringUtils.contains(clientVo.getGrantType(), grantType)) {
            log.info("客户端id: {} 认证类型：{} 异常!.", clientId, grantType);
            return R.fail("auth.grant.type.error");
        } else if (!Constants.NORMAL.equals(clientVo.getStatus())) {
            return R.fail("auth.grant.type.blocked");
        }
        // 登录
        LoginVO loginVo = IAuthStrategy.login(body, clientVo, grantType);

        return R.ok(loginVo);
    }

    /**
     * 获取系统的内置配置
     *
     * @return 配置信息
     */
    @GetMapping("/getConfig")
    public R<ConfigVO> getConfig() {
//        ConfigVO vo = loginService.getConfig();
        ConfigVO configVO = new ConfigVO();
        String property = SpringUtil.getProperty("security.captcha.enabled");
        configVO.setIsCaptchaOn(Boolean.parseBoolean(property));
        configVO.setIsPhoneRegisterOn(Boolean.parseBoolean(SpringUtil.getProperty("security.register.phoneEnabled")));
        configVO.setClientId(SpringUtil.getProperty("security.clientId"));
        configVO.setDictionary(DictCache.dictionaryCache());
        return R.ok(configVO);
    }

    /**
     * 退出登录
     */
    @PostMapping("/logout")
    public R<Void> logout() {
        loginService.logout();
        return R.ok("退出成功");
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    public R<Void> register(@Validated @RequestBody RegisterBody user) {
        loginService.register(user);
        return R.ok();
    }

    /**
     * 获取用户对应的菜单路由  用于动态生成路由
     * TODO 如果要在前端开启路由缓存的话 需要在ServerConfig.json 中  设置CachingAsyncRoutes=true  避免一直重复请求路由接口
     * @return 路由信息
     */
    @GetMapping("/getRouters")
    public R<List<RouterVO>> getRouters() {
        LoginUser loginUser =  LoginHelper.getLoginUser();
        List<RouterVO> routerTree = sysMenuService.getRouterTree(loginUser);
        return R.ok(routerTree);
    }
}
