package com.amms.service.impl;

import com.amms.domain.SysUser;
import com.amms.domain.dto.LoginParam;
import com.amms.domain.vo.Result;
import com.amms.mapper.SysUserMapper;
import com.amms.mapper.TouristMapper;
import com.amms.security.JwtUtils;
import com.amms.service.ISysUserService;
import com.amms.util.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.amms.security.SecurityUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class SysUserServiceImpl implements ISysUserService {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Value("${token.expireTime}")
    private Long expireTime;

    @Autowired
    private TouristMapper touristMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 登录方法
     * @param loginParam 登录参数
     * @return
     */
    @Override
    public Result login(LoginParam loginParam) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginParam.getUsername(), loginParam.getPassword());

        Authentication authenticate = null;
        try {
            authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        } catch (AuthenticationException e) {
            log.error("异常", e);
            log.error("用户名或密码错误==>{}", loginParam);
            return Result.error("用户名或密码错误！");
        }

        // 认证通过后，获取到登录的用户信息
        Object principal = authenticate.getPrincipal();
        SysUser loginUser = (SysUser) principal;
        if (loginUser == null) {
            return Result.error("用户名或密码错误！");
        }

        // 生成token，保存到redis中，并返回给前端token的id
        String tokenId = UUID.randomUUID().toString();

        // 将用户信息存储到redis中
        redisUtils.set(tokenId, loginUser, expireTime, TimeUnit.MINUTES);

        // 将tokenId通过JWT生成token，返回给前端
        Map<String, Object> map = new HashMap<>();
        map.put("tokenId", tokenId);

        String token = jwtUtils.createToken(map);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("token", token);
        loginUser.setPassword(null);
        resultMap.put("user", loginUser);

        return Result.success("登录成功！", resultMap);
    }

    /**
     * 查询用户列表
     *
     * @param sysUser 用户
     * @return 用户
     */
    @Override
    public List<SysUser> selectSysUserList(SysUser sysUser) {
        return sysUserMapper.selectSysUserList(sysUser);
    }

    /**
     * 查询用户
     *
     * @param username 用户
     * @return 用户
     */
    @Override
    public SysUser selectByUsername(String username) {
        return sysUserMapper.selectByUsername(username);
    }

    /**
     * 查询用户详情
     *
     * @param id 用户
     * @return 用户
     */
    @Override
    public SysUser selectById(Long id) {
        return sysUserMapper.selectById(id);
    }

    /**
     * 新增用户
     *
     * @param sysUser 用户
     * @return 结果
     */
    @Override
    public int insertSysUser(SysUser sysUser) {
        // 添加创建时间
        sysUser.setCreateTime(new Date());
        // 添加创建人
        sysUser.setCreator(SecurityUtils.getCurrentUser().getId());
        return sysUserMapper.insertSysUser(sysUser);
    }

    /**
     * 修改用户
     *
     * @param sysUser 用户
     * @return 结果
     */
    @Override
    public int updateSysUser(SysUser sysUser) {
        sysUser.setUpdateTime(new Date());
        sysUser.setUpdater(SecurityUtils.getCurrentUser().getId());
        int i = sysUserMapper.updateSysUser(sysUser);

        if (i > 0) {  // 如果修改成功，将redis中的用户信息和Security中的用户信息都更新
            // 将用户信息放到SecurityContext中
            SysUser fresh = sysUserMapper.selectById(sysUser.getId());
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(fresh, null, null);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        return i;
    }

    @Override
    public int registerTourist(SysUser sysUser) {
        sysUser.setCreateTime(new Date());
        if (sysUser.getStatus() == null) sysUser.setStatus(0);
        if (sysUser.getRole() == null) sysUser.setRole("2");
        if (sysUser.getPassword() != null) {
            sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        }
        int i = sysUserMapper.insertSysUser(sysUser);
        if (i > 0 && sysUser.getTourist() != null) {
            sysUser.getTourist().setId(sysUser.getId());
            return touristMapper.insertTourist(sysUser.getTourist()) > 0 ? 1 : 0;
        }
        return i;
    }

    /**
     * 删除用户
     *
     * @param id 用户主键
     * @return 结果
     */
    @Override
    public int deleteSysUserById(Long id) {
        return sysUserMapper.deleteSysUserById(id);
    }

}
