package com.kingdee.eas.custom.integration.base.service;

import com.kingdee.eas.custom.integration.base.config.AppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * OAuth 核心流程 Service
 *
 * 策略路由：通过 Spring 注入 {@code List<PlatformOAuthStrategy>} 自动收集所有
 * {@link PlatformOAuthStrategy} 实现 Bean，按 {@code platform()} 构建索引 Map，
 * 无需 switch-case 分支。
 *
 * 新增平台：实现 PlatformOAuthStrategy 并注册为 Spring Bean 即可，本类无需改动。
 *
 * 去掉 Redis/SessionStore 后，redirect 通过 state 参数随 OAuth 流程传递：
 *   认证入口：state = StateValidator.generate(redirect)  → 传入 OAuth URL
 *   回调处理：redirect = StateValidator.extractRedirect(state) → 取出后跳转
 */
@Service
public class OAuthService {

    private static final Logger log = LoggerFactory.getLogger(OAuthService.class);

    public static final String SESSION_USER_ID  = "AUTH_USER_ID";
    public static final String SESSION_PLATFORM = "AUTH_PLATFORM";

    /** 策略索引，key = platform() 返回值，如 "dingtalk"、"feishu" */
    private final Map<String, PlatformOAuthStrategy> strategyMap;

    public OAuthService(List<PlatformOAuthStrategy> strategies) {
        this.strategyMap = strategies.stream().collect(Collectors.toMap(
                PlatformOAuthStrategy::platform, Function.identity()));
        log.info("已注册 OAuth 平台策略: {}",
                strategyMap.keySet().stream().sorted().collect(Collectors.joining(", ")));
    }

    // -------------------------------------------------------------------------
    // 1. 构造 OAuth 授权 URL
    // -------------------------------------------------------------------------

    /**
     * 构造 OAuth 授权跳转 URL。
     *
     * @param config 应用配置
     * @param state  已编码 redirect 的 state 字符串（由 StateValidator.generate 生成）
     */
    public String buildAuthUrl(AppConfig config, String state) {
        PlatformOAuthStrategy strategy = requireStrategy(config.getPlatform());
        return strategy.buildAuthUrl(config, state);
    }

    // -------------------------------------------------------------------------
    // 2. 用 code 换取用户 userId
    // -------------------------------------------------------------------------

    /**
     * 用授权码换取用户身份标识，按平台自动路由。
     */
    public String getUserId(AppConfig config, String code) {
        PlatformOAuthStrategy strategy = requireStrategy(config.getPlatform());
        return strategy.getUserId(config, code);
    }

    // -------------------------------------------------------------------------
    // 3. 建立应用侧登录 session
    // -------------------------------------------------------------------------

    public void createUserSession(HttpServletRequest request,
                                  HttpServletResponse response,
                                  String userId,
                                  String platform) {
        HttpSession session = request.getSession(true);
        session.setAttribute(SESSION_USER_ID,  userId);
        session.setAttribute(SESSION_PLATFORM, platform);
        session.setMaxInactiveInterval(8 * 60 * 60);
        log.info("用户 session 已建立, userId={}, platform={}", userId, platform);
    }

    public boolean isAuthenticated(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        return session != null && session.getAttribute(SESSION_USER_ID) != null;
    }

    public String getCurrentUserId(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) return null;
        return (String) session.getAttribute(SESSION_USER_ID);
    }

    // -------------------------------------------------------------------------
    // 内部工具
    // -------------------------------------------------------------------------

    private PlatformOAuthStrategy requireStrategy(String platform) {
        PlatformOAuthStrategy strategy = strategyMap.get(platform);
        if (strategy == null) {
            throw new IllegalArgumentException(
                    "不支持的平台: " + platform + "，已注册: " + strategyMap.keySet());
        }
        return strategy;
    }
}
