package com.qmth.qrzk.repository.user.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.qmth.qrzk.dao.IRoleDao;
import com.qmth.qrzk.dao.IUserDao;
import com.qmth.qrzk.repository.common.base.BaseDao;
import com.qmth.qrzk.repository.exp.BaseData;
import com.qmth.qrzk.repository.exp.Teacher;
import com.qmth.qrzk.repository.service.query.UserQueryParams;
import com.qmth.qrzk.repository.user.model.Attachment;
import com.qmth.qrzk.repository.user.model.Course;
import com.qmth.qrzk.repository.user.model.ImportBean;
import com.qmth.qrzk.repository.user.model.Role;
import com.qmth.qrzk.repository.user.model.User;
import com.qmth.qrzk.repository.user.model.UserCourse;
import com.qmth.qrzk.repository.user.model.UserRole;
import com.qmth.qrzk.repository.user.service.IUserService;
import com.qmth.qrzk.repository.utils.CipherUtil;
import com.qmth.qrzk.repository.utils.Consts;
import com.qmth.qrzk.repository.utils.DateHelper;
import com.qmth.qrzk.repository.utils.General;
import com.qmth.qrzk.repository.utils.Md5EncryptUtils;

@Service("userServiceImpl")
public class UserServiceImpl implements IUserService {

	private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
	
	@Autowired
	@Qualifier("userDaoImpl")
	private IUserDao userDao;
	
	@Autowired
	private BaseDao dao;
	
	@Autowired
	@Qualifier("roleDaoImpl")
	private IRoleDao roleDao;
	
	@Autowired
	private CourseServiceImpl courseService;
	
	@Override
	public User loginUser(User user) {
		try {
			List<User> ls = userDao.selectUser(user);
			if(ls.size()>0){
				return ls.get(0);
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}


	@Override
	public int updateLastLoginDate(User user) {
		return userDao.updateLastLoginDate(user);
	}

	@Override
	public User getUserByLoginName(String loginName) {
		try{
			User user = userDao.getLoginUserByUsername(loginName);
			return user;
		}catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	
	public void deleteUser(User userTO){
		userDao.deleteUser(userTO);
		initUserInfo();
	}
	
	public void updateUser(User userTO){
		dao.update("updateUser",userTO);
		initUserInfo();
	}
	@Override
	public List<User> findUsers(List<Integer> ls) {
		return userDao.getUsersByCourse(ls);
	}


	@Override
	public List<User> queryUsers(UserQueryParams params) {
		if(params == null){
			return dao.getList("queryUsers");
		}else{
			return dao.getPagerList("queryUsers", params);
		}
	}

	@Override
	public int addUser(User user) {
		int num = userDao.insertUser(user);
		initUserInfo();
		return num;
	}


	@Override
	public int checkLoginName(Integer ownerId,String loginName) {
		if(ownerId == null){
			ownerId = 0;
		}
		User user = new User();
		user.setId(ownerId);
		user.setLoginName(loginName);
		Integer result = dao.get("checkUserNameWithoutSelf", user);
		return result;
	}


	@Override
	public int updatepassword(User user) {
		int num = userDao.updatePassword(user);
		initUserInfo();
		return num;
	}


	@Override
	public int updateisEnabled(User user) {
		int num = userDao.updateStatus(user);
		initUserInfo();
		return num;
	}


	@Override
	public User findById(int id) {
		return userDao.findUserById(id);
	}


	@Override
	public int checkPassword(User user) {
		return userDao.checkPassword(user);
	}


	@Override
	public List<User> getCanSetByUsers(int courseId) {
		return userDao.getCanSetByUsers(courseId);
	}
	
	@Override
	public List<User> queryUsersByCourseId(int courseId) {
		return dao.getList("queryUsersByCourseId", courseId);
	}

	@Override
	public List<User> queryTeachers(UserQueryParams params) {
		params.setUserType(Consts.USER_TYPE_TEACHER);
		return dao.getPagerList("queryTeachers", params);
	}
	
	@Override
	public List<User> querySecretarys(UserQueryParams params) {
		params.setUserType(Consts.USER_TYPE_SECRETARY);
		return dao.getPagerList("queryTeachers", params);
	}
	
	@Override
	public List<User> queryInputers(UserQueryParams params) {
		params.setUserType(Consts.USER_TYPE_INPUTER);
		return dao.getPagerList("queryTeachers", params);
	}


	@Override
	public int queryNameFromList(List<ImportBean> list) {
		return userDao.queryNameFromList(list);
	}


	@Override
	public int insertUserList(List<User> list) {
		int num = userDao.insertUserList(list);
		initUserInfo();
		return num;
	}

	@Override
	public User queryByName(String name) {
		List<User> users=userDao.queryName(name);
		if(users.size()>0){
			return users.get(0);
		}
		return null;
	}


	@Override
	public Map<String, Object> saveImportUser(int userType, List<ImportBean> list) {
		
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(list!=null&&list.size()!=0){
			//需要验证姓名
			int j=1;
			int successNum = 0;
			Role role = dao.get("findRoleByCode", Consts.ROLE_DOMESTIC_CONSUMER);
			List<User> importUsers = new ArrayList<User>();
			
			String msg = "";
			for(ImportBean bean:list){
				User user=this.queryByName(bean.getName());
				//校验数据库中是否存在该用户信息
				if(user!=null){
//					result.put("result", "fail");
//					result.put("lineNum", j);
					msg = msg + "第" + j + "行的用户[" + bean.getName() + "]已存在，自动忽略；";
//					result.put("msg", "登录名为:"+bean.getName() + "的用户在数据库中已存在!无法再次导入");
				}else{
					//insert into s_user(is_enabled,name,password,login_name,user_type,school,gender) 
					User us=new User();
					us.setName(bean.getName());
					us.setLoginName(bean.getName());
					us.setIsEnabled(1);
					us.setPassword("123456");
					us.setUserType(userType);
					us.setSchool(bean.getSchool());
					us.setGender(bean.getGender());
					us.setCertino(bean.getCertino());
					us.setPosition(bean.getPosition());
					us.setDepartment(bean.getDepartment());
					us.setMajor(bean.getMajor());
					us.setOfficePhone(bean.getOfficePhone());
					us.setPhone(bean.getPhone());
					us.setEmail(bean.getEmail());

					importUsers.add(us);
					successNum++;
				}
				j++;
			}
			if (result.isEmpty()) {
				for(User us : importUsers){
					addUser(us);
					UserRole ur = new UserRole();
					ur.setRoleId(role.getId());
					ur.setUserId(us.getId());
					roleDao.insert(ur);
				}
				
				result.put("result", "success");
				result.put("successNum", j-1);
				result.put("msg", msg.equals("")?"所有数据导入成功，共导入" + successNum + "条用户数据。" : "成功导入" + successNum + "条用户数据。" + msg.substring(0, msg.length() - 1) + "。");
				
			}
		}else{
			result.put("result", "error");
			result.put("msg", "导入失败!请检查导入模板的excel的正确性 以及是否导入了空excel!");
		}
		initUserInfo();		//重新更新缓存用户
		
		return result;
	}


	@Override
	public Map<String, Object> saveImportUserCourse(List<ImportBean> list) {
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(list!=null&&list.size()!=0){
			int j = 1;
			List<UserCourse> ls=new ArrayList<UserCourse>();
			boolean existsError = false;
			for(ImportBean bean:list){
				//课程代码为5位字符串
				if(bean.getCourseCode().length()!=5){
					existsError = true;
					result.put("result", "fail");
					result.put("lineNum", j);
					result.put("msg", bean.getCourseCode() + " 课程代码不是5位字符串！");
				}
				Course course=courseService.findByCode(bean.getCourseCode());
				if(course==null){
					existsError = true;
					result.put("result", "fail");
					result.put("lineNum", j);
					result.put("msg", bean.getCourseCode() +" 课程代码不存在!");
				}
				User user = queryByName(bean.getName());
				if(user==null){		//用户不存在则返回结果
					existsError = true;
					result.put("result", "fail");
					result.put("lineNum", j);
					result.put("msg", bean.getName()+" 用户姓名不存在!");
				}
				
				if(course != null && user != null){
					List<Course> userCourses = dao.getList("select-course", user.getId());

					boolean relationExists = false;
					for(Course dbUserCourse : userCourses){
						if(dbUserCourse.getId().equals(course.getId())){
							relationExists = true;
							existsError = true;
							result.put("result", "fail");
							result.put("lineNum", j);
							result.put("msg", "用户 " + bean.getName() + " 与课程代码 " + bean.getCourseCode() + "的对应关系已存在，请删除此行数据后重新导入。");
							break;
						}
					}

					if(!relationExists){
						UserCourse uc=new UserCourse();
						uc.setUserId(user.getId());
						uc.setCourseId(course.getId());
						ls.add(uc);
					}
				}
				j++;
			}
			
			if(!existsError){
				if(ls.size() > 0)
					courseService.addUserCourses(ls);
				result.put("result", "success");
				result.put("successNum", ls.size());
				result.put("msg", "导入成功!");
			}else{
				result.put("result", "fail");
			}
			
		}else{
			result.put("result", "error");
			result.put("msg", "导入失败!请检查导入命题教师与课程关联关系的excel的正确性 以及是否导入了空excel!");
		}
		initUserInfo();
		return result;
	}
	
	/**
	 * 重置缓存的用户信息
	 */
	public void initUserInfo(){
		try{
			List<User> users=queryUsers(null);
			for(User user:users){
				user.setPassword("");
				Consts.UserMap.put(user.getId(), user);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public Attachment expForClient(User curUser){
		Attachment zipAtt = null;
		UserQueryParams params = new UserQueryParams();
		params.setUserType(Consts.USER_TYPE_TEACHER);
		List<User> users = dao.getList("queryUsers",params);
		List<Teacher> teachers = new ArrayList<Teacher>(users.size());
		for(User u:users){
			Teacher t = new Teacher(u.getGuid(), u.getName(), u.getLoginName(), Md5EncryptUtils.md5(u.getPassword()));
			teachers.add(t);
		}
		BaseData expData = new BaseData(teachers);
		FileOutputStream fos = null;
		ZipOutputStream zos = null;
		try {
            JAXBContext context = JAXBContext.newInstance(BaseData.class);
            Marshaller marshaller = context.createMarshaller();
            File newFile = General.newTmpFile();
            fos = new FileOutputStream(newFile);
            zos = new ZipOutputStream(fos);
            zos.putNextEntry(new ZipEntry("baseData.xml"));
            marshaller.marshal(expData, zos);
            zos.closeEntry();
        	General.close(zos);
        	General.close(fos);
        	zos = null;
        	fos = null;
        	File destFile = General.newAttFile();
        	FileUtils.copyFile(newFile, destFile);
        	CipherUtil.encrypt(newFile,destFile,Consts.keyForService);
			
			zipAtt = new Attachment();
			zipAtt.setCreatedBy(curUser.getId());
			zipAtt.setOriginalName("BaseData-" + DateHelper.getNow(DateHelper.shortSimpleDateFormatWithoutSplit) + ".qrzk");
			zipAtt.setCurName(destFile.getName());
			zipAtt.setFileLength(destFile.length());
			zipAtt.setStorePath(destFile.getAbsolutePath());
			zipAtt.setStatus(Consts.AttachmentStatus.DRAFT);
			dao.insert("addAttachment", zipAtt);
        } catch (Exception e) {
        	throw new RuntimeException("写入zip压缩文件失败，原因：" + e.getMessage(), e);
        } finally{
        	General.close(zos);
        	General.close(fos);
        }
		return zipAtt;
	}
}
