package com.bcxin.survey.service;

import cn.hutool.core.bean.BeanUtil;
import com.bcxin.survey.dao.QueryHelper;
import com.bcxin.survey.dao.report.BaseDao;
import com.bcxin.survey.domain.activity.Activity;
import com.bcxin.survey.domain.security.Org;
import com.bcxin.survey.domain.security.Role;
import com.bcxin.survey.domain.security.User;
import com.bcxin.survey.domain.survey.SurveyAssist;
import com.bcxin.survey.service.security.UserDetailsServiceImpl;
import com.bcxin.survey.service.security.UserFacet;
import com.bcxin.survey.utils.*;
import com.bcxin.survey.vo.DwzPage;
import com.bcxin.survey.wechat.request.Oauth2AccessToken;
import com.bcxin.survey.wechat.utils.WeixinUtil;
import com.google.common.collect.Lists;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class UserServiceImpl implements UserService {

	@Autowired
	private BaseDao baseDao;

	@Autowired
	private BCryptPasswordEncoder bcryptEncoder;

	@Autowired
	private UserDetailsServiceImpl userdetailService;

	@Override
	public User getCurrentUser() {
		SecurityContext context = SecurityContextHolder.getContext();
		Authentication authentication = context.getAuthentication();
		if (authentication != null
				&& authentication.getPrincipal() instanceof UserFacet) {
			return ((UserFacet) authentication.getPrincipal()).subject();
		}
		return null;
	}

	/**
	 * 用户注册
	 */
	@Override
	public String register(HttpServletRequest request, MultipartFile certFile) {
		String userName = request.getParameter("userName");
		String password = request.getParameter("password");
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		String realName = request.getParameter("realName");

		User user = new User();
		user.setRealName(realName);
		user.setUserName(userName);
		user.setPassword(bcryptEncoder.encode(password));
		user.setPhone(phone);
		user.setEmail(email);
		user.setUserType(DictConst.USERTYPE_DSFFWJGYH);
//		user.setUserRoles(UserRole.CUSTOMER.toString());
		baseDao.save(user);

		return Const.BLANK_CHAR;
	}

	@Override
	public String resetPassword(String oldPassword, String password) {
		User current = getCurrentUser();
		if (bcryptEncoder.matches(oldPassword, current.getPassword())) {
			return "原密码错误，修改密码失败";
		}
		User currentUser = findUserByName(current.getUserName());
		currentUser.setPassword(bcryptEncoder.encode(password));
		baseDao.save(currentUser);
		return Const.BLANK_CHAR;
	}

	@Override
	public String restorePassword(String password) {
		User current = getCurrentUser();
		User currentUser = findUserByName(current.getUserName());
		currentUser.setPassword(bcryptEncoder.encode(password));
		baseDao.save(currentUser);
		return Const.BLANK_CHAR;
	}

	@Override
	public User selectUserByPerId(String perId) {
		List<Criterion> criterion = new ArrayList<Criterion>();
		criterion.add(Restrictions.eq("perId", perId));
		List<User> list= baseDao.findByCriterion(User.class, criterion);
		if(list!=null && list.size()>0){
			return list.get(0);
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public User findUserByName(String name) {
		List<Criterion> criterions = new ArrayList<Criterion>();
		criterions.add(Restrictions.eq("active", "1"));
		//TODO
		//#2757
		//criterions.add(Restrictions.or(Restrictions.eq("userName", name),Restrictions.eq("phone", name),Restrictions.eq("email", name)));
		criterions.add(Restrictions.eq("userName", name));
		List<User> userList = baseDao.findByCriterion(User.class, criterions);
		if(userList.size()>0) {
			return userList.get(0);
		}
		return null;
	}

	@Override
	public User findUserByOid(long oid) {
		return baseDao.get(User.class, oid);
	}

	/**
	 * 微信服务号获取用户信息
	 */
	@Override
	public User getCurrentUser(String weChat, String code) {
		User currentUser = getCurrentUser();
		if (currentUser == null) {
			if (StringUtil.isNotEmpty(code)) {
				Oauth2AccessToken oat = WeixinUtil.getAccessToken(GlobalResources.APPID,GlobalResources.APPSECRET, code);

				if (oat != null) {
					String userName = oat.getOpenid();
					System.out.println(userName);
					currentUser = findUserByName(userName);
				}
			}
		}
		return currentUser;
	}

	@Override
	public void setAuthentication(String userName, HttpServletRequest request) {
		// 根据用户名username加载userDetails
		UserDetails userDetails = userdetailService.loadUserByUsername(userName);
		// 根据userDetails构建新的Authentication,这里使用了
		// PreAuthenticatedAuthenticationToken当然可以用其他token,如UsernamePasswordAuthenticationToken
		PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(
				userDetails, userDetails.getPassword(),
				userDetails.getAuthorities());

		// 设置authentication中details
		authentication.setDetails(new WebAuthenticationDetails(request));

		// 存放authentication到SecurityContextHolder
		SecurityContextHolder.getContext().setAuthentication(authentication);
		HttpSession session = request.getSession(true);
		// 在session中存放security context,方便同一个session中控制用户的其他操作
		session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
	}

	@Override
	public Boolean checkPhoneMsg(String securityCode, String phone,HttpServletRequest request) {
		HttpSession session = request.getSession(true);
		String code = (String) session.getAttribute("yzkeyword" + phone);
		if (code != null && code.equals(securityCode)) {
			return true;
		}
		return false;
	}

	@Override
	public void save(User user) {
		baseDao.saveOrUpdate(user);

	}

	@Override
	public String getOpenId(String weChat, String code) {
		String openId = "";
		if (StringUtil.isNotEmpty(code)) {
			Oauth2AccessToken oat = WeixinUtil.getAccessToken(GlobalResources.APPID, GlobalResources.APPSECRET,	code);
			if (oat != null) {
				openId = oat.getOpenid();
			}
		}
		return openId;
	}

	@Override
	public Boolean checkPassword(User user, String oldPassword) {
		return bcryptEncoder.matches(oldPassword, user.getPassword());
	}

	@Override
	public void saveNewPassword(User user, String newPassword) {
		user.setPassword(bcryptEncoder.encode(newPassword));
		baseDao.saveOrUpdate(user);
	}


	@Override
	public Role findRoleByOid(Long oid) {
		return baseDao.get(Role.class, oid);
	}

	@Override
	public List<User> findUserListByOrgIdAndUserType(Long orgId, String userType) {
		List<Criterion> criterions = new ArrayList<Criterion>();
		criterions.add(Restrictions.eq("active", "1"));
		criterions.add(Restrictions.eq("userType", userType));
		if(orgId != null) {
			criterions.add(Restrictions.eq("org.oid", orgId));
		}
		return baseDao.findByCriterion(User.class, criterions);
	}

	@Override
	public List<User> findActivityExpertUser(SurveyAssist surveyAssist) {
		String expertsStr = surveyAssist.getExperts();
		StringBuffer stringBuffer = new StringBuffer();
		if (StringUtil.isNotEmpty(expertsStr)) {
			String[] experts = expertsStr.split("#");
			stringBuffer.append("(");
			int loop = 0;
			for (String oid : experts) {
				if (StringUtil.isEmpty(oid)) {
					continue;
				}
				if (loop == 0) {
					stringBuffer.append(oid);
				} else {
					stringBuffer.append(",").append(oid);
				}
				loop++;
			}
			stringBuffer.append(")");
		}
		List<User> userList = Lists.newArrayList();
		StringBuffer sql = new StringBuffer("select u.oid,u.realName,u.phone from risk_se_user u ");
		sql.append(" where u.active = 1 and u.userType='17'");
		if (StringUtil.isNotEmpty(stringBuffer.toString())) {
			sql.append(" and u.oid in " + stringBuffer.toString());
		} else {
			return userList;
		}
		System.out.println("查找活动选择的专家："+sql.toString());
		List<Object> list = QueryHelper.findBySql(sql.toString(), null);
		if (CollectionUtil.isNotEmpty(list)) {
			list.forEach(obj->{
				Map<String,Object> map = (HashMap<String,Object>)obj;
				User user = BeanUtil.mapToBean(map,User.class,true);
				userList.add(user);
			});
		}
		return userList;
	}


	@Override
	public List<User> findSurveyExpertUser(Activity activity){
		List<User> userList = Lists.newArrayList();
		StringBuffer sql = new StringBuffer();
		sql.append("select rsu.oid,rsu.realName,rsu.phone from risk_se_user rsu");
		sql.append(" INNER JOIN risk_activity_cooper rac on rsu.org_id= rac.org_id");
		sql.append(" where rsu.active=1 and rsu.userType='17'");
		sql.append(" and rac.activity_id="+activity.getOid());

		System.out.println("查找所有的专家："+sql.toString());
		List<Object> list = QueryHelper.findBySql(sql.toString(), null);
		if (CollectionUtil.isNotEmpty(list)) {
			list.forEach(obj->{
				Map<String,Object> map = (HashMap<String,Object>)obj;
				User user = BeanUtil.mapToBean(map,User.class,true);
				userList.add(user);
			});
		}

		return userList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<User> findAllUserListForManage(User user) {
		List<Criterion> criterions = new ArrayList<Criterion>();
		//TODO
		return baseDao.findByCriterion(User.class, criterions);
	}


	/**
	 * <b>Function </b> 
	 *
	 * @param user
	 * @param page
	 * @return
	 * @author LinQingLin
	 * @date 2016年12月21日 下午3:12:46
	 * @注意事项 </b>
	 * <b>
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<User> findAllUserListForPage(User user, DwzPage page) {
		List<Criterion> criterions = new ArrayList<Criterion>();

		//TODO
		if(StringUtil.isNotEmpty(page.getHtml())){
			criterions.add(Restrictions.or(Restrictions.like("realName", "%" + page.getHtml() + "%"),Restrictions.like("userName", "%" + page.getHtml() + "%"),Restrictions.like("phone", "%" + page.getHtml() + "%"),Restrictions.like("email", "%" + page.getHtml() + "%")));
		}
		Order order = Order.desc("createOn");
		if(StringUtil.isNotEmpty(page.getOrderField())){
			if(StringUtil.isEmpty(page.getOrderDirection()) || page.getOrderDirection().equals("asc")){
				order = Order.asc(page.getOrderField());
			}else{
				order = Order.desc(page.getOrderField());
			}
		}

		return baseDao.findByCriterionForPage(User.class, criterions, page, order);
	}

	/**
	 * 查询勘查经理和勘查区域经理
	 *
	 * @param oid
	 * @return
	 */
	@Override
	public List<User> listTKManager(Long oid) {
		List<User> userList = Lists.newArrayList();
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT * FROM risk_se_user WHERE  org_id in (SELECT org_id FROM risk_se_user WHERE oid = "+oid+") AND userType in (18)");
		List<Object> list = QueryHelper.findBySql(sql.toString(), null);
		if (CollectionUtil.isNotEmpty(list)) {
			list.forEach(obj -> {
				Map<String, Object> map = (HashMap<String, Object>) obj;
				User user = BeanUtil.mapToBean(map, User.class, true);
				userList.add(user);
			});
		}
		return userList;
	}

	@Override
	public List<User> findExpertUser(Long orgId, String userType){
		List<User> userList = Lists.newArrayList();
		String sql="select B.oid,B.realName,B.phone from risk_expertuser A,risk_se_user B where A.oid=B.oid ";
		sql+=" and A.checkStatus=2 and B.active=1 ";
		sql+=" and B.org_id="+orgId;
		sql+=" and B.userType='"+userType+"'";
		List<Object> list = QueryHelper.findBySql(sql.toString(), null);
		if (CollectionUtil.isNotEmpty(list)) {
			list.forEach(obj -> {
				Map<String, Object> map = (HashMap<String, Object>) obj;
				User user = BeanUtil.mapToBean(map, User.class, true);
				userList.add(user);
			});
		}
		return userList;
	}

	@Override
	public User selectServiceOrgRegister(Org org) {
		List<Criterion> criterion = Lists.newArrayList();
		criterion.add(Restrictions.eq("org", org));
		List list = baseDao.findByCriterion(User.class, criterion, Order.asc("oid"));
		if (list.size() > 0) {
			return (User) list.get(0);
		}
		return null;
	}

	@Override
	public List<User> selectServiceOrgPersonByList(List<String> userTypeList, Long oid) {
		List<Criterion> criterion = Lists.newArrayList();
		criterion.add(Restrictions.eq("org.oid", oid));
		criterion.add(Restrictions.in("userType", userTypeList));
		criterion.add(Restrictions.eq("active", DictConst.Y));
		return baseDao.findByCriterion(User.class, criterion);
	}



}
