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

import com.kingdee.eas.custom.integration.base.exception.CommonErrorCodes;
import com.kingdee.eas.custom.integration.base.exception.IntegrationException;
import com.kingdee.eas.custom.integration.base.config.AppConfig;
import com.kingdee.eas.custom.integration.base.bizEnum.DeviceType;
import com.kingdee.eas.custom.integration.base.service.detection.PlatformDetectionService;

import com.kingdee.eas.custom.integration.base.service.AppConfigService;
import com.kingdee.eas.custom.integration.base.service.StateValidator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * 统一认证入口控制器。
 *
 * <p>通过 User-Agent 识别平台和终端类型（移动端/桌面端），从 state 中提取 appType，
 * 转发到对应平台的认证控制器。不包含 OAuth 业务逻辑和平台检测逻辑。</p>
 *
 * <p>新增平台时只需实现 PlatformDetector 并注册为 Spring Bean，
 * 在 oauth-config.json 中添加对应条目，本类无需改动。</p>
 *
 * <p>待办链接格式（sHR 生成）：{@code /auth/unified?state=Base64Url(redirect|appType)}</p>
 */
@Controller
@RequestMapping("/auth")
public class UnifiedAuthController {

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

    private final AppConfigService appConfigService;
    private final StateValidator stateValidator;
    private final PlatformDetectionService detectionService;

    public UnifiedAuthController(AppConfigService appConfigService,
                                 StateValidator stateValidator,
                                 PlatformDetectionService detectionService) {
        this.appConfigService = appConfigService;
        this.stateValidator = stateValidator;
        this.detectionService = detectionService;
    }

    @GetMapping("/unified")
    public String unified(String state, HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (StringUtils.isBlank(state)) {
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "Invalid state");
        }

        String redirect = stateValidator.extractRedirect(state);
        if (StringUtils.isBlank(redirect)) {
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "Invalid state");
        }

        String appType = stateValidator.extractAppType(state);
        if (StringUtils.isBlank(appType)) {
            // 默认应用类型为 "pa"  流程助手
            appType = "pa";
        }

        String ua = request.getHeader("User-Agent");
        String platformBase = detectionService.detectBasePlatform(ua);
        if (platformBase == null) {
            log.warn("unsupported client, UA={}", ua);
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "unsupported_client");
        }

        DeviceType device = detectionService.detectDevice(ua);
        String platformFull = platformBase + (device != null ? "_" + device.name().toLowerCase() : "");

        String authEntry = appConfigService.getAuthEntry(platformBase, appType);
        if (authEntry == null) {
            log.warn("authEntry not found, platform={}, appType={}", platformBase, appType);
            throw new IntegrationException(CommonErrorCodes.SYSTEM_ERROR);
        }

        log.info("forward, platform={}, device={}, appType={}, entry={}",
                platformFull, device, appType, authEntry);
        return "forward:" + authEntry;
    }

    /**
     * 通过 appId 发起认证。
     *
     * <p>适用于客户端已知应用标识的场景，无需预先生成 state。
     * 根据 appId 查找配置，自动生成 state、检测平台并转发。</p>
     *
     * <p>请求格式：{@code GET /auth/app?appId=ding123&redirect=https://shr.example.com/home}</p>
     */
    @GetMapping("/app")
    public String app(@RequestParam String appId,
                      @RequestParam String redirect,
                      HttpServletRequest request,
                      HttpServletResponse response) throws IOException {
        if (StringUtils.isBlank(appId)) {
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "appId is required");
        }
        if (StringUtils.isBlank(redirect)) {
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "redirect is required");
        }

        AppConfig config = appConfigService.getByAppId(appId);
        if (config == null) {
            log.warn("appId not found: {}", appId);
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "config_not_found");
        }

        String state = stateValidator.generate(redirect, config.getAppType());

        String ua = request.getHeader("User-Agent");
        // 消息「查看详情」常在外部浏览器打开，UA 无 Lark/Feishu；appId 已能确定平台
        String platformBase = detectionService.detectBasePlatform(ua);
        if (platformBase == null) {
            platformBase = config.getPlatform();
            log.info("UA 未识别为飞书/钉钉客户端，使用 appId 对应平台: platform={}, appId={}",
                    platformBase, appId);
        }
        if (StringUtils.isBlank(platformBase)) {
            log.warn("unsupported client, UA={}", ua);
            throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "unsupported_client");
        }

        DeviceType device = detectionService.detectDevice(ua);
        String platformFull = platformBase + (device != null ? "_" + device.name().toLowerCase() : "");

        log.info("app auth, appId={}, platform={}, device={}, appType={}, redirect={}",
                appId, platformFull, device, config.getAppType(), redirect);
        return "forward:" + config.getAuthEntry() + "?state=" + URLEncoder.encode(state, "UTF-8");
    }

}
