package com.vetti.framework.web.service;

import javax.annotation.Resource;

import com.vetti.common.core.domain.AjaxResult;
import com.vetti.common.core.domain.dto.LoginDto;
import com.vetti.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.vetti.common.constant.CacheConstants;
import com.vetti.common.constant.Constants;
import com.vetti.common.constant.UserConstants;
import com.vetti.common.core.domain.entity.SysUser;
import com.vetti.common.core.domain.model.LoginUser;
import com.vetti.common.core.redis.RedisCache;
import com.vetti.common.exception.ServiceException;
import com.vetti.common.exception.user.BlackListException;
import com.vetti.common.exception.user.CaptchaException;
import com.vetti.common.exception.user.CaptchaExpireException;
import com.vetti.common.exception.user.UserNotExistsException;
import com.vetti.common.exception.user.UserPasswordNotMatchException;
import com.vetti.common.utils.DateUtils;
import com.vetti.common.utils.MessageUtils;
import com.vetti.common.utils.StringUtils;
import com.vetti.common.utils.ip.IpUtils;
import com.vetti.framework.manager.AsyncManager;
import com.vetti.framework.manager.factory.AsyncFactory;
import com.vetti.framework.security.context.AuthenticationContextHolder;
import com.vetti.system.service.ISysConfigService;
import com.vetti.system.service.ISysUserService;

/**
 * 登录校验方法
 * 
 * @author ruoyi
 */
@Component
public class SysLoginService
{
    @Autowired
    private TokenService tokenService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;
    
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysConfigService configService;

    /**
     * 登录验证
     * 
     * @param username 用户名
     * @param password 密码
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public LoginDto login(String username, String password, String code, String uuid)
    {
        LoginDto loginDto = new LoginDto();

        // 验证码校验
//        validateCaptcha(username, code, uuid);
        // 登录前置校验
        loginPreCheck(username, password);
        // 用户验证
        Authentication authentication = null;
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        loginDto.setToken(tokenService.createToken(loginUser));
        loginDto.setUserId(loginUser.getUserId());
        SysUser user = userService.selectUserById(loginUser.getUserId());
        loginDto.setUser(user);

        return loginDto;

    }

    /**
     * 校验验证码
     * 
     * @param username 用户名
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid)
    {
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        if (captchaEnabled)
        {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
            String captcha = redisCache.getCacheObject(verifyKey);
            if (captcha == null)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
                throw new CaptchaExpireException();
            }
            redisCache.deleteObject(verifyKey);
            if (!code.equalsIgnoreCase(captcha))
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                throw new CaptchaException();
            }
        }
    }

    /**
     * 登录前置校验
     * @param username 用户名
     * @param password 用户密码
     */
    public void loginPreCheck(String username, String password)
    {
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // 用户名不在指定范围内 错误
//        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
//                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
//        {
//            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
//            throw new UserPasswordNotMatchException();
//        }
        // IP黑名单校验
        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
            throw new BlackListException();
        }
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

    /**
     * 忘记密码
     *
     * @param username 用户名
     * @param password 密码
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public void resetPassword(String username, String password, String repeatPassword, String code, String uuid)
    {
        //校验验证码
        boolean isOperationLogin = "1234".equals(code);
        String verifyKey = CacheConstants.VERIFICATION_EMAIL_CODE_KEY + username;
        if (!isOperationLogin) {
            String codeResult = redisCache.getCacheObject(verifyKey);
            if (codeResult == null || !codeResult.equals(code)) {
                throw new ServiceException(MessageUtils.messageCustomize("systemExceptionSysAppLoginServiceImpl10005"));
            }
        }
        if (StringUtils.isEmpty(username))
        {
            throw new ServiceException(MessageUtils.messageCustomize("systemSysLoginService10001"));
        }
        else if (StringUtils.isEmpty(password))
        {
            throw new ServiceException(MessageUtils.messageCustomize("systemSysLoginService10002"));
        }
        //校验用户是否存在
        SysUser sysUser = userService.selectUserByUserName(username);
        if(sysUser == null){
            throw new ServiceException(MessageUtils.messageCustomize("systemSysLoginService10003"));
        }
        //校验密码是否一致
        if(!password.equals(repeatPassword)){
            throw new ServiceException(MessageUtils.messageCustomize("systemSysLoginService10004"));
        }
        //进行密码修改
        sysUser.setPassword(password);
        userService.resetUserPwd(sysUser.getUserId(), SecurityUtils.encryptPassword(password));
    }

    /**
     * 退出登录
     *
     * @param loginUser 登录用户信息
     */
    public void logout(LoginUser loginUser)
    {
        if (loginUser != null)
        {
            String token = loginUser.getToken();
            
            // TODO: 安全功能集成 - 更新会话状态为已登出
            // 在用户退出登录时，更新hotake_security_login_sessions表中的会话状态
            // 记录登出时间，并将is_active设置为0
            try {
                Object securityService = com.vetti.common.utils.spring.SpringUtils.getBean("hotakeSecurityServiceImpl");
                if (securityService != null) {
                    // 使用反射调用更新会话状态的方法
                    java.lang.reflect.Method method = securityService.getClass().getMethod(
                        "updateSessionLogout", String.class);
                    method.invoke(securityService, token);
                }
            } catch (Exception e) {
                // 更新会话状态失败不影响退出流程
            }
            
            // 删除用户缓存记录
            tokenService.delLoginUser(token);
        }
    }

}
