package cn.nianxx.thhotel.platform.security.service.impl;

import cn.nianxx.thhotel.platform.security.common.dto.AuthenticatedUserContext;
import cn.nianxx.thhotel.platform.security.service.CurrentUserContextService;
import cn.nianxx.thhotel.platform.security.service.FrontendAuthorizationService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

/**
 * 前端业务接口强制鉴权服务实现。复用可选 token 解析结果，并返回业务接口专用错误码。
 */
@Service
public class FrontendAuthorizationServiceImpl implements FrontendAuthorizationService {

    private final CurrentUserContextService currentUserContextService;
    private final HttpServletRequest request;

    /**
     * 注入当前用户上下文服务和原始请求，用于区分缺少 token 与 token 失效。
     */
    public FrontendAuthorizationServiceImpl(
            CurrentUserContextService currentUserContextService,
            HttpServletRequest request) {
        this.currentUserContextService = currentUserContextService;
        this.request = request;
    }

    /**
     * 要求当前请求已登录；没有有效 token 时返回前端业务接口专用 401。
     */
    @Override
    public AuthenticatedUserContext requireLogin() {
        return currentUserContextService.currentUser()
                .orElseThrow(this::missingOrInvalidLogin);
    }

    /**
     * 要求当前请求用户拥有指定业务权限码；已登录但无权限时返回 403。
     */
    @Override
    public AuthenticatedUserContext requirePermission(String permissionCode) {
        AuthenticatedUserContext context = requireLogin();
        if (permissionCode == null || permissionCode.isBlank()
                || !context.permissionCodes().contains(permissionCode)) {
            throw new FrontendAuthorizationException(
                    HttpStatus.FORBIDDEN,
                    "FRONTEND_PERMISSION_DENIED",
                    "当前用户没有访问该业务能力的权限。");
        }
        return context;
    }

    /**
     * 根据 Authorization 头判断是未登录还是登录态失效，便于前端做统一提示。
     */
    private FrontendAuthorizationException missingOrInvalidLogin() {
        String authorizationHeader = request.getHeader("Authorization");
        if (hasBearerToken(authorizationHeader)) {
            return new FrontendAuthorizationException(
                    HttpStatus.UNAUTHORIZED,
                    "AUTH_SESSION_INVALID",
                    "登录已失效，请重新登录。");
        }
        return new FrontendAuthorizationException(
                HttpStatus.UNAUTHORIZED,
                "AUTH_TOKEN_REQUIRED",
                "请先登录后再访问该业务能力。");
    }

    /**
     * 判断请求是否提供了非空 Bearer token。
     */
    private boolean hasBearerToken(String authorizationHeader) {
        if (authorizationHeader == null || authorizationHeader.isBlank()) {
            return false;
        }
        String prefix = "Bearer ";
        return authorizationHeader.regionMatches(true, 0, prefix, 0, prefix.length())
                && !authorizationHeader.substring(prefix.length()).trim().isBlank();
    }
}
