package org.xyzh.auth.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.xyzh.api.auth.service.AuthService;
import org.xyzh.api.message.service.MessageService;
import org.xyzh.api.system.service.SysUserService;
import org.xyzh.api.system.vo.SysUserVO;
import org.xyzh.common.core.domain.LoginParam;
import org.xyzh.common.core.domain.LoginDomain;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.redis.service.RedisService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @description    AuthController.java文件描述 认证控制器
 * @filename    AuthController.java
 * @author    yslg
 * @copyright xyzh
 * @since 2025-09-28
 */
@RestController
@RequestMapping("/auth")
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private AuthService authService;

    @DubboReference(version = "1.0.0", group = "system", timeout = 5000, check = false, retries = 0)
    private SysUserService userService;

    @DubboReference(version = "1.0.0", group = "message", timeout = 5000, check = false, retries = 0)
    private MessageService messageService;

    @Autowired
    private RedisService redisService;

    /**
     * @description    用户登录
     * @param    loginParam 登录参数
     * @return    ResultDomain<LoginDomain> 登录结果
     * @author    yslg
     * @since 2025-09-28
     */
    @PostMapping("/login")
    public ResultDomain<LoginDomain> login(@RequestBody LoginParam loginParam, HttpServletRequest request) {
        // 从 request 中提取客户端 IP 并设置到 loginParam
        loginParam.setClientIp(getClientIP(request));
        return authService.login(loginParam);
    }

    /**
     * @description    用户退出登录
     * @param    loginDomain 登录域对象
     * @return    ResultDomain<String> 退出结果
     * @author    yslg
     * @since 2025-09-28
     */
    @PostMapping("/logout")
    public ResultDomain<LoginDomain> logout(HttpServletRequest request) {
        String token = extractTokenFromRequest(request);
        return authService.logout(token);
    }

    /**
     * @description    获取验证码（统一接口，支持多种类型）
     * @param    loginParam 登录参数（包含验证码类型）
     * @return    ResultDomain<LoginDomain> 验证码结果
     * @author    yslg
     * @since 2025-12-09
     */
    @PostMapping("/captcha")
    public ResultDomain<LoginDomain> getCaptcha(@RequestBody LoginParam loginParam) {
        return authService.getCaptcha(loginParam);
    }

    /**
     * @description    刷新令牌
     * @param    request HTTP请求
     * @return    ResultDomain<LoginDomain> 新的登录信息
     * @author    yslg
     * @since 2025-12-09
     */
    @PostMapping("/refresh")
    public ResultDomain<LoginDomain> refreshToken(HttpServletRequest request) {
        String token = extractTokenFromRequest(request);
        String clientIp = getClientIP(request);
        return authService.refreshToken(token, clientIp);
    }

    /**
     * @description    健康检查
     * @return    ResultDomain<String> 健康状态
     * @author    yslg
     * @since 2025-09-28
     */
    @GetMapping("/health")
    public ResultDomain<String> health() {
        return ResultDomain.success("认证服务运行正常", "OK");
    }

    /**
     * @description    发送邮箱验证码
     * @param    requestBody 包含email字段的请求体
     * @return    ResultDomain<LoginDomain> 发送结果
     * @author    yslg
     * @since 2025-12-09
     */
    @PostMapping("/send-email-code")
    public ResultDomain<LoginDomain> sendEmailCode(@RequestBody Map<String, String> requestBody) {
        String email = requestBody.get("email");
        
        LoginParam loginParam = new LoginParam();
        loginParam.setEmail(email);
        loginParam.setLoginType("email");
        
        return authService.getCaptcha(loginParam);
    }

    /**
     * @description    发送手机验证码
     * @param    requestBody 包含phone字段的请求体
     * @return    ResultDomain<LoginDomain> 发送结果
     * @author    yslg
     * @since 2025-12-09
     */
    @PostMapping("/send-sms-code")
    public ResultDomain<LoginDomain> sendSmsCode(@RequestBody Map<String, String> requestBody) {
        String phone = requestBody.get("phone");
        
        LoginParam loginParam = new LoginParam();
        loginParam.setPhone(phone);
        loginParam.setLoginType("sms");
        
        return authService.getCaptcha(loginParam);
    }

    /**
     * @description    用户注册
     * @param    requestBody 注册参数
     * @return    ResultDomain<LoginDomain> 注册结果
     * @author    yslg
     * @since 2025-11-03
     */
    @PostMapping("/register")
    public ResultDomain<LoginDomain> register(@RequestBody Map<String, Object> requestBody, HttpServletRequest request) {
        try {
            // 获取注册参数
            String registerType = (String) requestBody.get("registerType");
            String username = (String) requestBody.get("username");
            String phone = (String) requestBody.get("phone");
            String email = (String) requestBody.get("email");
            String password = (String) requestBody.get("password");
            String confirmPassword = (String) requestBody.get("confirmPassword");
            String smsCode = (String) requestBody.get("smsCode");
            String emailCode = (String) requestBody.get("emailCode");
            String smsSessionId = (String) requestBody.get("smsSessionId");
            String emailSessionId = (String) requestBody.get("emailSessionId");
            String studentId = (String) requestBody.get("studentId");
            
            // 1. 参数验证
            if (password == null || password.trim().isEmpty()) {
                return ResultDomain.failure("密码不能为空");
            }
            
            if (password.length() < 6) {
                return ResultDomain.failure("密码至少6个字符");
            }
            
            if (!password.equals(confirmPassword)) {
                return ResultDomain.failure("两次输入的密码不一致");
            }
            
            // 2. 根据注册类型进行不同的验证
            SysUserVO user = new SysUserVO();
            
            switch (registerType) {
                case "username":
                    // 用户名注册
                    if (username == null || username.trim().isEmpty()) {
                        return ResultDomain.failure("用户名不能为空");
                    }
                    if (username.length() < 3 || username.length() > 20) {
                        return ResultDomain.failure("用户名长度为3-20个字符");
                    }
                    if (!username.matches("^[a-zA-Z0-9_]+$")) {
                        return ResultDomain.failure("用户名只能包含字母、数字和下划线");
                    }
                    user.setUsername(username);
                    logger.info("用户名注册: {}", username);
                    break;
                    
                case "phone":
                    // 手机号注册
                    if (phone == null || phone.trim().isEmpty()) {
                        return ResultDomain.failure("手机号不能为空");
                    }
                    if (!phone.matches("^1[3-9]\\d{9}$")) {
                        return ResultDomain.failure("手机号格式不正确");
                    }
                    if (smsCode == null || smsCode.trim().isEmpty()) {
                        return ResultDomain.failure("请输入手机验证码");
                    }
                    if (smsSessionId == null || smsSessionId.trim().isEmpty()) {
                        return ResultDomain.failure("会话已失效，请重新获取验证码");
                    }
                    
                    // 通过sessionId验证手机验证码
                    String smsCodeKey = "sms:code:" + smsSessionId;
                    String storedSmsValue = redisService.get(smsCodeKey, String.class);
                    if (storedSmsValue == null) {
                        return ResultDomain.failure("验证码已过期，请重新获取");
                    }
                    
                    // 解析存储的值：手机号:验证码
                    String[] smsParts = storedSmsValue.split(":");
                    if (smsParts.length != 2) {
                        return ResultDomain.failure("验证码数据异常");
                    }
                    
                    String storedPhone = smsParts[0];
                    String storedSmsCode = smsParts[1];
                    
                    // 验证手机号和验证码是否匹配
                    if (!storedPhone.equals(phone)) {
                        logger.warn("手机号注册验证失败，提交手机号: {}, 验证码绑定手机号: {}", phone, storedPhone);
                        return ResultDomain.failure("手机号与验证码不匹配");
                    }
                    if (!storedSmsCode.equals(smsCode)) {
                        return ResultDomain.failure("验证码错误");
                    }
                    
                    // 验证码使用后删除
                    redisService.delete(smsCodeKey);
                    
                    user.setPhone(phone);
                    user.setUsername(phone); // 使用手机号作为用户名
                    logger.info("手机号注册: {}, sessionId: {}", phone, smsSessionId);
                    break;
                    
                case "email":
                    // 邮箱注册
                    if (email == null || email.trim().isEmpty()) {
                        return ResultDomain.failure("邮箱不能为空");
                    }
                    if (!email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
                        return ResultDomain.failure("邮箱格式不正确");
                    }
                    if (emailCode == null || emailCode.trim().isEmpty()) {
                        return ResultDomain.failure("请输入邮箱验证码");
                    }
                    if (emailSessionId == null || emailSessionId.trim().isEmpty()) {
                        return ResultDomain.failure("会话已失效，请重新获取验证码");
                    }
                    
                    // 通过sessionId验证邮箱验证码
                    String emailCodeKey = "email:code:" + emailSessionId;
                    String storedEmailValue = redisService.get(emailCodeKey, String.class);
                    if (storedEmailValue == null) {
                        return ResultDomain.failure("验证码已过期，请重新获取");
                    }
                    
                    // 解析存储的值：邮箱:验证码
                    String[] emailParts = storedEmailValue.split(":");
                    if (emailParts.length != 2) {
                        return ResultDomain.failure("验证码数据异常");
                    }
                    
                    String storedEmail = emailParts[0];
                    String storedEmailCode = emailParts[1];
                    
                    // 验证邮箱和验证码是否匹配
                    if (!storedEmail.equals(email)) {
                        logger.warn("邮箱注册验证失败，提交邮箱: {}, 验证码绑定邮箱: {}", email, storedEmail);
                        return ResultDomain.failure("邮箱与验证码不匹配");
                    }
                    if (!storedEmailCode.equals(emailCode)) {
                        return ResultDomain.failure("验证码错误");
                    }
                    
                    // 验证码使用后删除
                    redisService.delete(emailCodeKey);
                    
                    user.setEmail(email);
                    user.setUsername(email.split("@")[0]); // 使用邮箱前缀作为用户名
                    logger.info("邮箱注册: {}, sessionId: {}", email, emailSessionId);
                    break;
                    
                default:
                    return ResultDomain.failure("未知的注册类型");
            }
            
            // 3. 设置密码（明文，Service层会加密）
            user.setPassword(password);
            
            // 4. 设置用户状态为正常
            user.setStatus("0");
            
            // 5. 调用UserService注册用户（Service层会加密密码）
            ResultDomain<TbSysUserDTO> registerResult = userService.registerUser(user);
            
            if (!registerResult.getSuccess()) {
                return ResultDomain.failure(registerResult.getMessage());
            }
            
            logger.info("用户注册成功: {}", user.getUsername());
            
            // 6. 注册成功后自动登录
            LoginParam loginParam = new LoginParam();
            loginParam.setUsername(user.getUsername());
            loginParam.setPassword(password);
            loginParam.setLoginType("password");
            
            if (phone != null && !phone.trim().isEmpty()) {
                loginParam.setPhone(phone);
            }
            if (email != null && !email.trim().isEmpty()) {
                loginParam.setEmail(email);
            }
            
            loginParam.setClientIp(getClientIP(request));
            ResultDomain<LoginDomain> loginResult = authService.login(loginParam);
            
            if (loginResult.getSuccess()) {
                return ResultDomain.success("注册成功", loginResult.getData());
            } else {
                // 注册成功但登录失败，返回注册成功信息
                return ResultDomain.success("注册成功，请登录", loginResult.getData());
            }
            
        } catch (Exception e) {
            logger.error("用户注册失败", e);
            return ResultDomain.failure("注册失败: " + e.getMessage());
        }
    }

    /**
     * 从请求中提取Token
     */
    private String extractTokenFromRequest(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }
        return null;
    }

    /**
     * 获取客户端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();
        }
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}
