package com.huatek.frame.base.service.impl;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.net.NetUtil;
import com.huatek.frame.base.util.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.huatek.frame.base.config.CustomRsaProperties;
import com.huatek.frame.base.utils.RsaUtils;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.huatek.frame.base.dto.UserDTO;
import com.huatek.frame.base.entity.User;
import com.huatek.frame.base.mapper.DictionnaireMapper;
import com.huatek.frame.base.mapper.LoginMapper;
import com.huatek.frame.base.mapper.UserDao;
import com.huatek.frame.base.service.LoginService;
import com.huatek.frame.base.util.Constants;
import com.huatek.frame.base.vo.PermissionVO;
import com.huatek.frame.base.vo.UserVO;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;
import com.huatek.torch.sql.beans.LocalUser;
import com.huatek.torch.util.jwt.TokenMgr;
import com.huatek.torch.util.md5.Md5;
import com.huatek.torch.util.tools.UserUtil;
import com.huatek.torch.util.uuid.Uuid;

/**
 * @author key
 */
@Slf4j
@Component
@Service(interfaceClass = LoginService.class)
@Transactional(rollbackFor = Exception.class)
public class LoginServiceImpl implements LoginService {

	@Value("${dangle.dat.path}")
	private String danglePath;

	@Value("${dangle.dat.ip}")
	private String ip;

	@Value("${dangle.dat.mac}")
	private String mac;

	@Autowired
	private LoginMapper loginMapper;

	@Autowired
	private DictionnaireMapper dictionnaireMapper;

	@Autowired
	private UserDao userDao;

	@Autowired(required = true)
	private RedisTemplate<String, String> redisTemplate;

	@Override
	public Map<String, Object> login(UserDTO user, long time, String tag, String code, boolean verify) throws Exception{

		if(!verifyDongle()){
			return ResultUtil.put(Md5Util.DANGLE_CODE_FAIL, "", null);
		}
		ValueOperations<String, String> operations = redisTemplate.opsForValue();
		if (verify) {
			if (StringUtils.isEmpty(code)) {
				return ResultUtil.put(ConstantUtil.JWT_CODE_FAIL, "LOGIN.CODE.NOTNULL", null);
			}
			if (!redisTemplate.hasKey(tag)) {
				return ResultUtil.put(ConstantUtil.JWT_CODE_FAIL, "LOGIN.CODE.TIMEOUT", null);
			} else {
				String redisCode = operations.get(tag);
				if (!redisCode.equalsIgnoreCase(code)) {
					return ResultUtil.put(ConstantUtil.JWT_CODE_FAIL, "LOGIN.CODE.ERROR", null);
				}
			}
		}

		UserVO userLogin = loginMapper.login(user);
		if (userLogin == null) {
			return ResultUtil.put(ConstantUtil.JWT_CODE_FAIL, "LOGIN.NAMEORPWDW.EEOR", null);
		}
		Map<String, Object> param = new HashMap<String, Object>(2);
		param.put("id", userLogin.getId());
		param.put("deleted", Constants.DEFAULT_NO);
		String newPwd = RsaUtils.decryptByPrivateKey( CustomRsaProperties.privateKey, user.getPassword() );
		String password = Md5.getMD5Code(userLogin.getPasswordSalt() + newPwd);
		String longinPassword = userLogin.getPassword();
		if (longinPassword.equals(password)) {

			String userCode = ConstantUtil.PERMISSIONS + userLogin.getId().hashCode();
			List<PermissionVO> permissions = loginMapper.findByUserId(param);
			StringBuilder buttons = new StringBuilder();
			for (PermissionVO permission : permissions) {
				buttons.append(permission.getPermission() + ",");
			}
			// 把当前用户的权限放入redis 覆盖之前的
			operations.set(userCode, JSONObject.toJSONString(permissions));
			Map<String, String> map = new HashMap<String, String>(4);
			String uid = userLogin.getId();
			// 登陆验证通过后--用户信息
			LocalUser sub = new LocalUser(uid, userLogin.getUserName(), userLogin.getUserMobile(),
					userLogin.getUserEmail(), userLogin.getUserPhone(), userLogin.getLeader(), userLogin.getGroupId(),
					userLogin.getLanguageType(), time);
			String token = TokenMgr.createJWT(Uuid.getUUID(), ConstantUtil.JWT_ISS, TokenMgr.generalSubject(sub), time);
			String dics = JSONObject.toJSONString(dictionnaireMapper.selectDictionnaires(Constants.DEFAULT_NO));
			map.put("username", userLogin.getUserName());
			map.put("dics", dics);
			map.put("buttons", buttons.toString());
			return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "", map, token);
		} else {
			return ResultUtil.put(ConstantUtil.JWT_CODE_FAIL, "LOGIN.NAMEORPWDW.EEOR", null);
		}
	}

	@Override
	public Map<String, Object> deleteRedis(String token) {
		redisTemplate.delete(ConstantUtil.PERMISSIONS + UserUtil.getUid(token).hashCode());
		return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "", "");
	}

	public  boolean verifyDongle() throws UnknownHostException {
		String path=danglePath;
		File file = new File(path);
		List list = new ArrayList();
		String sourse="";
		if (file.exists()) {
			try {
				//将文件的每行为一个元素添加到list中
				list = Files.readAllLines(file.toPath(), Charset.defaultCharset());
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			if (list.isEmpty()){
				return false;
			}

		}else{
			return false;
		}
		for (Object line : list) {
			sourse+=line;
		}
		String sourseNew =Md5Util.md5(Md5Util.DANGLE_CONTENT+ip+mac).toUpperCase();
		if(sourse.equals(sourseNew)){
			return true;
		}else{
			return false;
		}

	}
	@Override
	public Map<String, Object> changePwd(String token, Map<String, String> map) {
		String oldPwd = map.get("oldPwd");
		String newPwd = map.get("newPwd");
		String confirmPwd = map.get("confirmPwd");
		if (newPwd.equals(confirmPwd)) {
			String uid = UserUtil.getUid(token);
			User user = userDao.get(uid);
			String pwd = user.getPassword();
			String oldPwdBack = Md5.getMD5Code(user.getPasswordSalt() + oldPwd);
			if (pwd.equals(oldPwdBack)) {
				String newPwdBack = Md5.getMD5Code(user.getPasswordSalt() + newPwd);
				User userBack = new User();
				userBack.setId(uid);
				userBack.setPassword(newPwdBack);
				userDao.updateLocal(userBack);
				return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "", "");
			} else {
				return ResultUtil.put(ConstantUtil.REQUEST_FAIL, "LOGIN.OLD.EEOR", null);
			}
		} else {

			return ResultUtil.put(ConstantUtil.REQUEST_FAIL, "LOGIN.CONFIRMPWD.EEOR", null);
		}
	}
}
