package org.xyzh.auth.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.xyzh.api.auth.login.LoginService;
import org.xyzh.api.system.user.UserService;
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.user.TbSysUser;
import org.xyzh.common.utils.IDUtils;
import org.xyzh.common.utils.EmailUtils;
import org.xyzh.common.utils.SmsUtils;
import org.xyzh.common.redis.service.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
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 LoginService loginService;

    @Autowired
    private UserService userService;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private RedisService redisService;

    @Autowired
    private PasswordEncoder passwordEncoder;
    /**
     * @description    用户登录
     * @param    loginParam 登录参数
     * @return    ResultDomain<LoginDomain> 登录结果
     * @author    yslg
     * @since 2025-09-28
     */
    @PostMapping("/login")
    public ResultDomain<LoginDomain> login(@RequestBody LoginParam loginParam, HttpServletRequest request) {
        return loginService.login(loginParam, request);
    }

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

    /**
     * @description    获取验证码
     * @return    ResultDomain<String> 验证码
     * @author    yslg
     * @since 2025-09-28
     */
    @GetMapping("/captcha")
    public ResultDomain<String> getCaptcha() {
        // TODO: 实现验证码生成逻辑
        ResultDomain<String> result = new ResultDomain<>();
        
        // 生成验证码会话ID，用于验证时匹配
        String captchaId = IDUtils.generateID();
        String captchaData = captchaId + ":captcha-placeholder";  // 格式: ID:验证码内容
        
        result.success("验证码获取成功", captchaData);
        return result;
    }

    /**
     * @description    刷新令牌
     * @param    token 原令牌
     * @return    ResultDomain<String> 新令牌
     * @author    yslg
     * @since 2025-09-28
     */
    @PostMapping("/refresh")
    public ResultDomain<String> refreshToken(@RequestHeader("Authorization") String token) {
        // TODO: 实现令牌刷新逻辑
        ResultDomain<String> result = new ResultDomain<>();
        
        // 为新令牌生成唯一ID
        String newTokenId = IDUtils.generateID();
        String newToken = "new-token-" + newTokenId;  // 临时占位符
        
        result.success("令牌刷新成功", newToken);
        return result;
    }

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

    /**
     * @description    发送邮箱验证码
     * @param    requestBody 包含email字段的请求体
     * @return    ResultDomain<Boolean> 发送结果
     * @author    yslg
     * @since 2025-11-03
     */
    @PostMapping("/send-email-code")
    public ResultDomain<Map<String, String>> sendEmailCode(@RequestBody Map<String, String> requestBody) {
        ResultDomain<Map<String, String>> result = new ResultDomain<>();
        
        String email = requestBody.get("email");
        
        // 验证邮箱格式
        if (email == null || email.trim().isEmpty()) {
            result.fail("邮箱不能为空");
            return result;
        }
        
        String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
        if (!email.matches(emailRegex)) {
            result.fail("邮箱格式不正确");
            return result;
        }
        
        // 检查是否频繁发送（60秒内只能发送一次）
        String rateLimitKey = "email:code:ratelimit:" + email;
        if (redisService.hasKey(rateLimitKey)) {
            result.fail("验证码已发送，请勿重复发送");
            return result;
        }
        
        // 生成会话ID（用于绑定验证码和用户）
        String sessionId = IDUtils.generateID();
        
        // 生成6位数字验证码
        String code = EmailUtils.generateVerificationCode();
        
        // 发送邮件
        boolean success = emailUtils.sendVerificationCode(email, code);
        
        if (success) {
            // 将验证码存储到Redis，绑定sessionId，有效期5分钟
            String codeKey = "email:code:" + sessionId;
            String codeValue = email + ":" + code;  // 格式：邮箱:验证码
            redisService.set(codeKey, codeValue, 5, TimeUnit.MINUTES);
            
            // 设置5分钟的发送频率限制
            redisService.set(rateLimitKey, "1", 5, TimeUnit.MINUTES);
            
            // 返回sessionId给前端
            Map<String, String> data = Map.of(
                "sessionId", sessionId,
                "message", "验证码已发送到邮箱"
            );
            
            logger.info("邮箱验证码已发送，邮箱: {}, sessionId: {}", email, sessionId);
            result.success("验证码已发送到邮箱", data);
        } else {
            result.fail("验证码发送失败，请稍后重试");
        }
        
        return result;
    }

    /**
     * @description    发送手机验证码
     * @param    requestBody 包含phone字段的请求体
     * @return    ResultDomain<Boolean> 发送结果
     * @author    yslg
     * @since 2025-11-03
     */
    @PostMapping("/send-sms-code")
    public ResultDomain<Map<String, String>> sendSmsCode(@RequestBody Map<String, String> requestBody) {
        ResultDomain<Map<String, String>> result = new ResultDomain<>();
        
        String phone = requestBody.get("phone");
        
        // 验证手机号格式
        if (phone == null || phone.trim().isEmpty()) {
            result.fail("手机号不能为空");
            return result;
        }
        
        if (!SmsUtils.isValidPhone(phone)) {
            result.fail("手机号格式不正确");
            return result;
        }
        
        // 检查是否频繁发送（60秒内只能发送一次）
        String rateLimitKey = "sms:code:ratelimit:" + phone;
        if (redisService.hasKey(rateLimitKey)) {
            result.fail("验证码已发送，请勿重复发送");
            return result;
        }
        
        // 生成会话ID（用于绑定验证码和用户）
        String sessionId = IDUtils.generateID();
        
        // 生成6位数字验证码
        String code = SmsUtils.generateVerificationCode();
        
        // 发送短信
        boolean success = smsUtils.sendVerificationCode(phone, code);
        
        if (success) {
            // 将验证码存储到Redis，绑定sessionId，有效期5分钟
            String codeKey = "sms:code:" + sessionId;
            String codeValue = phone + ":" + code;  // 格式：手机号:验证码
            redisService.set(codeKey, codeValue, 5, TimeUnit.MINUTES);
            
            // 设置5分钟的发送频率限制
            redisService.set(rateLimitKey, "1", 5, TimeUnit.MINUTES);
            
            // 返回sessionId给前端
            Map<String, String> data = Map.of(
                "sessionId", sessionId,
                "message", "验证码已发送"
            );
            
            logger.info("短信验证码已发送，手机号: {}, sessionId: {}", phone, sessionId);
            result.success("验证码已发送", data);
        } else {
            result.fail("验证码发送失败，请稍后重试");
        }
        
        return result;
    }

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