package top.continew.admin.config.satoken;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpInterface;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.mapper.DeptMapper;
import top.continew.admin.system.model.entity.DeptDO;
import top.continew.starter.auth.satoken.autoconfigure.SaTokenExtensionProperties;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.validate.CheckUtils;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Sa-Token 配置
 *
 * @author Charles7c
 * @since 2022/12/19 22:13
 */
@Configuration
@RequiredArgsConstructor
public class SaTokenConfiguration {

    @Value("${depts.routers}")
    private String routers;
    @Resource
    private DeptMapper deptMapper;

    private final SaTokenExtensionProperties properties;
    private final LoginPasswordProperties loginPasswordProperties;

    /**
     * Sa-Token 权限认证配置
     */
    @Bean
    public StpInterface stpInterface() {
        return new SaTokenPermissionImpl();
    }

    /**
     * SaToken 拦截器配置
     */
    @Bean
    public SaInterceptor saInterceptor() {
        return new SaInterceptor(handle -> SaRouter.match(StringConstants.PATH_PATTERN)
            .notMatch(properties.getSecurity().getExcludes())
            .check(r -> {
                HttpServletRequest request = (HttpServletRequest)SaHolder.getRequest().getSource();
                String servletPath = PathTemplateExtractor.getStaticPath(request);
                LoginUser loginUser = LoginHelper.getLoginUserSafely();
                if (loginUser == null) {
                    // 如果用户未登录，则跳过此检查
                    return;
                }
                Long deptId = loginUser.getDeptId();
                DeptDO deptDO = deptMapper.selectById(deptId);
                String routers = deptDO.getRouters();
                List<String> collect = Arrays.stream(this.routers.split(",")).collect(Collectors.toList());
                if (!collect.contains(servletPath)) {
                    return;
                }
                if (!StringUtils.hasText(routers)) {
                    throw new RuntimeException("用户所属学校无权限！");
                }
                if (routers.contains(servletPath)) {
                    return;
                } else {
                    throw new RuntimeException("用户所属学校无权限！");
                }
            })
            .check(r -> {
                LoginUser loginUser = LoginHelper.getLoginUserSafely();
                if (loginUser == null) {
                    // 如果用户未登录，则跳过此检查
                    return;
                }
                if (SaRouter.isMatchCurrURI(loginPasswordProperties.getExcludes())) {
                    return;
                }
                CheckUtils.throwIf(loginUser.isPasswordExpired(), "密码已过期，请修改密码");
            }));
    }

}