package com.platform.modules.sys.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.platform.common.exception.RRException;
import com.platform.common.utils.*;
import com.platform.modules.app.form.AppUserInfoForm;
import com.platform.modules.plm.util.MateriaFileProperties;
import com.platform.modules.plm.util.MaterialUtils;
import com.platform.modules.sys.dao.SysUserDao;
import com.platform.modules.sys.entity.SysTenantEntity;
import com.platform.modules.sys.entity.SysUserEntity;
import com.platform.modules.sys.entity.SysUserRoleEntity;
import com.platform.modules.sys.service.*;
import com.platform.modules.sys.vo.SysUserInfoVo;
import com.platform.modules.video.service.RealPathResolver;
import net.sf.json.JSONObject;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统用户
 */
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
	@Autowired
	private SysUserRoleService sysUserRoleService;
	@Autowired
	private SysRoleService sysRoleService;
	@Autowired
	private SysTenantService tenantService;
	@Autowired
	private SysUserTokenService sysUserTokenService;
	@Autowired
	private MateriaFileProperties materiaFileProperties;
	@Autowired
	private RealPathResolver realPathResolver;
	@Autowired
	private RedisUtils redisUtils;

	@Override
	public PageUtils queryPage(Map<String, Object> params) {
		// String realname = (String) params.get("realname");
		// Long createUserId = (Long) params.get("createUserId");
		Long tenantId = null;
		int current = 1;
		int size = 10;
		String username = (String) params.get("username");
		String strTenantId = (String) params.get("tenantId");
		String strPage = (String) params.get("page");
		String strLimit = (String) params.get("limit");
		Page<SysUserInfoVo> page = new Page<>();

		if (StringUtils.isNotBlank(strTenantId))
			tenantId = Long.valueOf(strTenantId);
		if (StringUtils.isNotBlank(strPage))
			current = Integer.valueOf(strPage);
		if (StringUtils.isNotBlank(strLimit))
			size = Integer.valueOf(strLimit);

		page.setCurrent(current);
		page.setSize(size);

		List<SysUserEntity> list = baseMapper.selectUserPage(page, username, tenantId);

//		Page<SysUserEntity> page = this.selectPage(new Query<SysUserEntity>(params).getPage(),
//				new EntityWrapper<SysUserEntity>().like(StringUtils.isNotBlank(username), "username", username)
//						.like(StringUtils.isNotBlank(realname), "realname", realname)
//						// .eq(createUserId != null, "create_user_id", createUserId)
//						.eq(null != tenantId, "tenant_id", tenantId)
//						.eq("status", 1));

		// List<SysUserEntity> userEntityList = page.getRecords();

		if (null == list || list.size() == 0)
			return new PageUtils(page);

//		for (SysUserEntity entity : list){
//			if (null != entity.getTenantId()){
//				if (redisUtils.hexists(Constant.REDIS_SYS_TENANT_ENTITY, entity.getTenantId().toString())){
//					entity.setTenantName(redisUtils.hget(Constant.REDIS_SYS_TENANT_ENTITY, entity.getTenantId().toString(), SysTenantEntity.class).getTenantName());
//				}else {
//					SysTenantEntity tenantEntity = tenantService.selectById(entity.getTenantId());
//					if (tenantEntity != null) {
//						redisUtils.hset(Constant.REDIS_SYS_TENANT_ENTITY, tenantEntity.getId().toString(), tenantEntity);
//						entity.setTenantName(tenantEntity.getTenantName());
//					}
//				}
//			}
//		}
//		List<SysUserInfoVo> voList = new ArrayList<>();
//		list.forEach(entity -> {
//			SysUserInfoVo infoVo = new SysUserInfoVo(entity);
//			voList.add(infoVo);
//		});
		List<SysUserInfoVo> voList = list.stream()
				.map(entity -> {
					SysUserInfoVo infoVo = new SysUserInfoVo(entity);
					// 拼接头像地址
					String userImg = infoVo.getUserImg();
					if (StringUtils.isNotBlank(userImg)){
						infoVo.setUserImg(materiaFileProperties.getBasePath() + userImg);
					}
					return infoVo;
				})
				.collect(Collectors.toList());
		page.setRecords(voList);
		return new PageUtils(page);
	}

	/**
	 * 获取用户基本信息
	 * 
	 * @param userId
	 *            用户ID
	 * @return
	 */
	@Override
	public SysUserEntity selectBaseById(Long userId) {
		if (null == userId) {
			return null;
		}
		SysUserEntity entity = null;
		Object strObject = redisUtils.hget(RedisKeys.getSysUserKey(), RedisKeys.getSysUserFeild(userId));
		if (null == strObject) {
			entity = this.selectById(userId);
			if (null != entity) {
				Map<String, Object> entityMap = new HashMap<>();
				entityMap.put("userId", entity.getUserId());
				entityMap.put("username", entity.getUsername());
				entityMap.put("realname", entity.getRealname());
				entityMap.put("email", entity.getEmail());
				entityMap.put("mobile", entity.getMobile());
				redisUtils.hset(RedisKeys.getSysUserKey(), RedisKeys.getSysUserFeild(userId), entityMap);
			}
		} else {
			entity = (SysUserEntity) JSONObject.toBean(JSONObject.fromObject(strObject), SysUserEntity.class);
		}
		return entity;
	}

	@Override
	public List<String> queryAllPerms(Long userId) {
		return baseMapper.queryAllPerms(userId);
	}

	@Override
	public List<Long> queryAllMenuId(Long userId) {
		return baseMapper.queryAllMenuId(userId);
	}

	@Override
	public SysUserEntity queryByUserName(String username) {
		return baseMapper.queryByUserName(username);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void save(SysUserEntity user) {
		user.setCreateTime(new Date());
		// sha256加密
		String salt = RandomStringUtils.randomAlphanumeric(20);
		user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
		user.setSalt(salt);
		this.insert(user);

		// 检查角色是否越权
//		checkRole(user);

		// 保存用户与角色关系
		sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void save(SysUserEntity user, MultipartFile materialFile) throws IOException {
//		try {
			user.setCreateTime(new Date());
			// sha256加密
			String salt = RandomStringUtils.randomAlphanumeric(20);
			user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
			user.setSalt(salt);
			// 处理用户头像
			handlerUserImg(user, materialFile);
			if (user.getStatus() == null) {
				user.setStatus(1);
			}
			this.insert(user);

			// 检查角色是否越权
//			checkRole(user);
			// 保存用户与角色关系
			sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void update(SysUserEntity user) {
		if (StringUtils.isBlank(user.getPassword())) {
			user.setPassword(null);
		} else {
			user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
		}
		this.updateById(user);

		// 检查角色是否越权
//		checkRole(user);

		// 保存用户与角色关系
		sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void update(SysUserEntity user, MultipartFile materialFile) {
		try {

			// 用户所属机构状态为0时，不能进行修改操作
			if (null != user.getTenantId()){
				// 根据tenant_id获取机构信息
				SysTenantEntity tenantEntity = tenantService.selectOne(new EntityWrapper<SysTenantEntity>().eq("tenant_id", user.getTenantId()));
				if (null != tenantEntity.getStatus() && 0 == tenantEntity.getStatus()){
					throw new Exception("用户所属机构状态为0时，不能进行修改操作");
				}
			}

			if (StringUtils.isBlank(user.getPassword())) {
				user.setPassword(null);
			} else {
				user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
			}
			// 处理用户头像
			handlerUserImg(user, materialFile);
			// 用户状态为禁用时，踢出已登录的该用户
			if (null != user.getStatus() && user.getStatus().equals(0)){
				sysUserTokenService.logout(user.getUserId());
			}
			this.updateById(user);

			// 检查角色是否越权
//			checkRole(user);
			// 保存用户与角色关系
			sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 处理用户新增、修改中头像文件
	 * 
	 * @param userEntity
	 *            用户信息
	 * @param materialFile
	 *            用户头像资源
	 * @throws IOException
	 */
	private void handlerUserImg(SysUserEntity userEntity, MultipartFile materialFile) throws IOException {
		// 更新报道时，媒体资源更新后才会传入文件，否则无需更新
		if (materialFile != null && !materialFile.isEmpty()) {
			String newMaterialName = FileUtils.createFileName() + "."
					+ FileUtils.getSuffix(materialFile.getOriginalFilename());
			String serverMaterialPath = materiaFileProperties.getMediaPath() + "/" + MaterialUtils.getDateDir() + "/"
					+ newMaterialName;
			String newMaterialPath = realPathResolver.get(materiaFileProperties.getMateriaPath() + serverMaterialPath);
			FileUtils.copy(materialFile.getInputStream(), newMaterialPath);
			userEntity.setUserImg(serverMaterialPath);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateLastLogin(SysUserEntity user) {
		this.updateById(user);
	}

	@Override
	public void deleteBatch(Long[] userId) {
		this.deleteBatchIds(Arrays.asList(userId));
		// 踢出要删除且已登录的该用户
		for (Long id : userId){
			sysUserTokenService.logout(id);
		}
	}

	@Override
	public boolean updatePassword(Long userId, String password, String newPassword) {
		SysUserEntity userEntity = new SysUserEntity();
		userEntity.setPassword(newPassword);
		return this.update(userEntity,
				new EntityWrapper<SysUserEntity>().eq("user_id", userId).eq("password", password));
	}

	@Override
	public List<SysUserEntity> selectByRoleId(Integer roleId) {
		if (roleId == null) {
			return null;
		}
		List<SysUserRoleEntity> userRoleEntities = sysUserRoleService
				.selectList(new EntityWrapper<SysUserRoleEntity>().eq("role_id", roleId));
		List<SysUserEntity> list = new ArrayList<>();
		if (userRoleEntities != null && userRoleEntities.size() > 0) {
			Long tenantId = null;
			SysUserEntity user = ShiroUtils.getUserEntity();
			if (user != null) {
				tenantId = user.getTenantId();
			}
			for (SysUserRoleEntity userRoleEntity : userRoleEntities) {
				SysUserEntity userEntity = selectById(userRoleEntity.getUserId());
				if (userEntity != null && (tenantId == null || tenantId.equals(userEntity.getTenantId()))) {
					list.add(userEntity);
				}
			}
		}
		return list;
	}

	/**
	 * 检查角色是否越权
	 */
	private void checkRole(SysUserEntity user) {
		if (user.getRoleIdList() == null || user.getRoleIdList().size() == 0) {
			return;
		}
		// 如果不是超级管理员，则需要判断用户的角色是否自己创建
		if (user.getCreateUserId() == Constant.SUPER_ADMIN) {
			return;
		}

		// 查询用户创建的角色列表
		List<Long> roleIdList = sysRoleService.queryRoleIdList(user.getCreateUserId());

		// 判断是否越权
		if (!roleIdList.containsAll(user.getRoleIdList())) {
			throw new RRException("新增用户所选角色，不是本人创建");
		}
	}

	@Override
	public SysUserEntity queryByMobile(String mobile) {
		return baseMapper.queryByMobile(mobile);
	}

	@Override
	@Transactional
	public R updateUserInfo(AppUserInfoForm userInfoForm, Long userId) {
		SysUserEntity userEntity = selectById(userId);
		if (userEntity == null) {
			return R.error("错误token");
		}
		String email = userInfoForm.getEmail();
//		String name = userInfoForm.getName();
		String mobile = userInfoForm.getMobile();
		// TODO: 2019/7/5 用户名改为真实姓名
		String realname = userInfoForm.getRealname();
//		EntityWrapper<SysUserEntity> wrapper = new EntityWrapper<>();
//		wrapper.eq("username", name);
//		wrapper.notIn("user_id", userId);
//		Integer count = selectCount(wrapper);
//		if (count > 0) {
//			return R.error("该名称已存在");
//		}
//		if (StringUtils.isNotBlank(name)) {
//			userEntity.setUsername(name);
//		}
		
		if (StringUtils.isNotBlank(realname)) {
			userEntity.setRealname(realname);
		}

		// TODO: 2019/3/13 仅修改用户名
		// if (StringUtils.isNotBlank(email)) {
		// userEntity.setEmail(email);
		// }
		// if (StringUtils.isNotBlank(mobile)) {
		// userEntity.setMobile(mobile);
		// }
		updateById(userEntity);
		
		Map<String, Object> entityMap = new HashMap<>();
		entityMap.put("userId", userEntity.getUserId());
		entityMap.put("username", userEntity.getUsername());
		entityMap.put("realname", userEntity.getRealname());
		entityMap.put("email", userEntity.getEmail());
		entityMap.put("mobile", userEntity.getMobile());
		redisUtils.hset(RedisKeys.getSysUserKey(), RedisKeys.getSysUserFeild(userId), entityMap);
		
		return R.ok();
	}

	@Override
	public String updateUserImg(SysUserEntity userEntity, MultipartFile multipartFile) {
		try {
			handlerUserImg(userEntity, multipartFile);
			updateById(userEntity);
			return userEntity.getUserImg();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public String checkExist(Long userId, String username, String mobile, String email) {
		if (StringUtils.isBlank(username) && StringUtils.isBlank(mobile) && StringUtils.isBlank(email)) {
			return null;
		}
		List<SysUserEntity> list = baseMapper.checkExist(userId, username, mobile, email);
		if (null == list || list.size()<=0) {
			return null;
		}
		for (SysUserEntity user : list) {
			if (StringUtils.isNotBlank(user.getUsername()) && user.getUsername().equals(username)) {
				return "用户名已存在！";
			} else if (StringUtils.isNotBlank(user.getEmail()) && user.getEmail().equals(email)) {
				return "邮箱已存在！";
			} else if (StringUtils.isNotBlank(user.getMobile()) &&  user.getMobile().equals(mobile)) {
				return "手机号已存在！";
			}
		}
		return null;
	}
}
