/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.controller
 * @ClassName: SsoController
 * @Description: SSO单点登录控制器，通过ES接口验证ticket并生成JWT Token
 * @Author: 张志锋
 * @Date: 2025-10-31
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.controller;

import com.alibaba.fastjson2.JSONObject;
import com.zhpb.gdyd_zhpb_zgf.dto.SsoLoginResponse;
import com.zhpb.gdyd_zhpb_zgf.entity.mysql.SsoLog;
import com.zhpb.gdyd_zhpb_zgf.entity.mysql.User;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.SsoLogRepository;
import com.zhpb.gdyd_zhpb_zgf.service.UserService;
import com.zhpb.gdyd_zhpb_zgf.utils.HttpClientUtils;
import com.zhpb.gdyd_zhpb_zgf.utils.JwtUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

/**
 * SSO单点登录控制器
 */
@RestController
@RequestMapping("/api/v1/sso")
@Tag(name = "单点登录", description = "SSO单点登录相关接口")
public class SsoController {

    @Autowired
    private UserService userService;
    
    @Autowired
    private SsoLogRepository ssoLogRepository;
    
    @Value("${sso.es-base-url:http://es-integration.es-uat-paas:8890}")
    private String esBaseUrl;
    
    @Value("${sso.getUserInfoPath:/bi/getUserInfoByTicket}")
    private String getUserInfoPath;

    /**
     * SSO登录接口
     * 
     * @param ticket SSO票据
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     * @throws IOException IO异常
     */
    @GetMapping("/login")
    @Operation(
            summary = "SSO单点登录",
            description = "通过ES接口验证ticket，获取用户信息并生成JWT Token返回给前端。用户不存在则自动创建。"
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "登录成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = SsoLoginResponse.class),
                            examples = @ExampleObject(
                                    name = "登录成功示例",
                                    value = "{\n" +
                                            "  \"code\": 200,\n" +
                                            "  \"message\": \"登录成功\",\n" +
                                            "  \"data\": {\n" +
                                            "    \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n" +
                                            "    \"userId\": \"n001\",\n" +
                                            "    \"userName\": \"张三\",\n" +
                                            "    \"projectId\": \"0001\"\n" +
                                            "  }\n" +
                                            "}"
                            )
                    )
            ),
            @ApiResponse(
                    responseCode = "302",
                    description = "Ticket验证失败，重定向到登录页",
                    content = @Content
            )
    })
    public void ssoLogin(
            @Parameter(
                    description = "SSO票据，从ES系统获取",
                    required = true,
                    example = "ticket_abc123xyz456"
            )
            @RequestParam String ticket,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        
        // 创建日志对象
        SsoLog ssoLog = new SsoLog();
        ssoLog.setTicket(ticket);
        ssoLog.setLoginIp(getClientIp(request));
        ssoLog.setLoginTime(LocalDateTime.now());
        ssoLog.setCreateTime(LocalDateTime.now());
        
        try {
            // 1. 调用ES接口验证ticket
            String time = String.valueOf(System.currentTimeMillis());
            String esUrl = esBaseUrl + getUserInfoPath + "?ticket=" + ticket + "&time=" + time;
            ssoLog.setRequestUrl(esUrl);
            
            String result = HttpClientUtils.doGet(esUrl);
            ssoLog.setResponseData(result);
            
            JSONObject res = JSONObject.parseObject(result);
            
            if (res.getInteger("ret") != 200) {
                String errorMsg = res.getString("msg");
                ssoLog.setLoginStatus("FAILED");
                ssoLog.setErrorMsg("Ticket验证失败: " + errorMsg);
                ssoLogRepository.save(ssoLog);
                
                // URL编码中文参数
                String encodedError = URLEncoder.encode("ticket无效", StandardCharsets.UTF_8);
                response.sendRedirect("/login?error=" + encodedError);
                return;
            }

            // 2. 解析用户信息
            JSONObject data = res.getJSONObject("data");
            String userId = data.getString("id");
            String name = data.getString("name");
            String projectId = data.getString("projectid");
            
            ssoLog.setUserId(userId);
            ssoLog.setUserName(name);
            ssoLog.setProjectId(projectId);

            // 3. 检查用户是否存在，不存在则创建
            User user = userService.findByUserId(userId);
            if (user == null) {
                user = userService.createUser(userId, name, projectId);
            } else {
                // 更新项目ID（如果需要）
                if (projectId != null && !projectId.equals(user.getProjectId())) {
                    user.setProjectId(projectId);
                    user.setUpdateTime(LocalDateTime.now());
                    userService.updateUser(user);
                }
            }

            // 4. 生成JWT Token
            String token = JwtUtils.generateToken(userId, name);
            ssoLog.setToken(token);
            ssoLog.setLoginStatus("SUCCESS");

            // 5. 保存登录日志
            ssoLogRepository.save(ssoLog);

            // 6. 将Token和用户信息返回给前端
            JSONObject responseData = new JSONObject();
            responseData.put("code", 200);
            responseData.put("message", "登录成功");
            JSONObject userData = new JSONObject();
            userData.put("token", token);
            userData.put("userId", userId);
            userData.put("userName", name);
            userData.put("projectId", projectId);
            responseData.put("data", userData);
            
            // 设置响应头
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(responseData.toJSONString());
            
        } catch (Exception e) {
            // 记录错误日志
            ssoLog.setLoginStatus("ERROR");
            ssoLog.setErrorMsg("登录异常: " + e.getMessage());
            ssoLogRepository.save(ssoLog);
            
            // URL编码中文参数
            String encodedError = URLEncoder.encode("登录失败", StandardCharsets.UTF_8);
            response.sendRedirect("/login?error=" + encodedError);
        }
    }
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

