package com.tashow.cloud.system.controller.admin.auth;

import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertSet;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.enums.UserTypeEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.security.security.config.SecurityProperties;
import com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthLoginReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthLoginRespVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthRegisterReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSmsSendReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
import com.tashow.cloud.system.convert.auth.AuthConvert;
import com.tashow.cloud.system.dal.dataobject.permission.MenuDO;
import com.tashow.cloud.system.dal.dataobject.permission.RoleDO;
import com.tashow.cloud.system.dal.dataobject.user.AdminUserDO;
import com.tashow.cloud.system.service.auth.AdminAuthService;
import com.tashow.cloud.system.service.permission.MenuService;
import com.tashow.cloud.system.service.permission.PermissionService;
import com.tashow.cloud.system.service.permission.RoleService;
import com.tashow.cloud.system.service.social.SocialClientService;
import com.tashow.cloud.system.service.user.AdminUserService;
import com.tashow.cloud.systemapi.enums.logger.LoginLogTypeEnum;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/** 管理后台 - 认证 */
@RestController
@RequestMapping("/system/auth")
@Validated
@Slf4j
public class AuthController {

  @Resource private AdminAuthService authService;
  @Resource private AdminUserService userService;
  @Resource private RoleService roleService;
  @Resource private MenuService menuService;
  @Resource private PermissionService permissionService;
  @Resource private SocialClientService socialClientService;

  @Resource private SecurityProperties securityProperties;

  /** 使用账号密码登录 */
  @PostMapping("/login")
  @PermitAll
  public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
    return success(authService.login(reqVO));
  }

  /** 登出系统 */
  @PostMapping("/logout")
  @PermitAll
  public CommonResult<Boolean> logout(HttpServletRequest request) {
    String token =
        SecurityFrameworkUtils.obtainAuthorization(
            request, securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
    if (StrUtil.isNotBlank(token)) {
      authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
    }
    return success(true);
  }

  /** 刷新令牌 */
  @PostMapping("/refresh-token")
  @PermitAll
  public CommonResult<AuthLoginRespVO> refreshToken(
      @RequestParam("refreshToken") String refreshToken) {
    return success(authService.refreshToken(refreshToken));
  }

  /** 获取登录用户的权限信息 */
  @GetMapping("/get-permission-info")
  public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
    // 1.1 获得用户信息
    AdminUserDO user = userService.getUser(getLoginUserId());
    if (user == null) {
      return success(null);
    }

    // 1.2 获得角色列表
    Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
    if (CollUtil.isEmpty(roleIds)) {
      return success(
          AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
    }
    List<RoleDO> roles = roleService.getRoleList(roleIds);
    roles.removeIf(
        role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色

    // 1.3 获得菜单列表
    Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
    List<MenuDO> menuList = menuService.getMenuList(menuIds);
    menuList = menuService.filterDisableMenus(menuList);

    // 2. 拼接结果返回
    return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
  }

  /** 注册用户 */
  @PostMapping("/register")
  @PermitAll
  public CommonResult<AuthLoginRespVO> register(
      @RequestBody @Valid AuthRegisterReqVO registerReqVO) {
    return success(authService.register(registerReqVO));
  }

  // ========== 短信登录相关 ==========
  /** 使用短信验证码登录 */
  @PostMapping("/sms-login")
  @PermitAll
  public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
    return success(authService.smsLogin(reqVO));
  }

  /** 发送手机验证码 */
  @PostMapping("/send-sms-code")
  @PermitAll
  public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
    authService.sendSmsCode(reqVO);
    return success(true);
  }

  /** 重置密码 */
  @PostMapping("/reset-password")
  @PermitAll
  public CommonResult<Boolean> resetPassword(@RequestBody @Valid AuthResetPasswordReqVO reqVO) {
    authService.resetPassword(reqVO);
    return success(true);
  }

  // ========== 社交登录相关 ==========
  /** 社交授权的跳转 */
  @GetMapping("/social-auth-redirect")
  @PermitAll
  public CommonResult<String> socialLogin(
      @RequestParam("type") Integer type, @RequestParam("redirectUri") String redirectUri) {
    return success(
        socialClientService.getAuthorizeUrl(type, UserTypeEnum.ADMIN.getValue(), redirectUri));
  }

  /** 社交快捷登录，使用 code 授权码", description = "适合未登录的用户，但是社交账号已绑定用户 */
  @PostMapping("/social-login")
  @PermitAll
  public CommonResult<AuthLoginRespVO> socialQuickLogin(
      @RequestBody @Valid AuthSocialLoginReqVO reqVO) {
    return success(authService.socialLogin(reqVO));
  }
}
