package com.uas.account.service;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.uas.account.AccountConfig;
import com.uas.account.core.Const;
import com.uas.account.core.ICallable;
import com.uas.account.core.Logger;
import com.uas.account.core.Page;
import com.uas.account.core.Status;
import com.uas.account.core.util.ExecuteUtils;
import com.uas.account.dao.PartnershipRecordDao;
import com.uas.account.dao.UserDao;
import com.uas.account.dao.UserSpaceDao;
import com.uas.account.entity.App;
import com.uas.account.entity.InvitationRecord;
import com.uas.account.entity.PartnershipRecord;
import com.uas.account.entity.Token;
import com.uas.account.entity.User;
import com.uas.account.entity.UserDetail;
import com.uas.account.entity.UserFailed;
import com.uas.account.entity.UserSpace;
import com.uas.account.entity.UserSpaceAndUserInfo;
import com.uas.account.entity.UserSpaceDetail;
import com.uas.account.entity.UserSpaceDetailInfo;
import com.uas.account.entity.UserSpaceFailed;
import com.uas.account.entity.UserView;
import com.uas.account.exception.VisibleError;
import com.uas.account.util.BeanUtil;
import com.uas.account.viewmodel.UserSpaceDetailView;
import com.uas.dfs.service.FileClient;
import com.uas.sso.common.util.HttpUtil;
import com.uas.sso.common.util.HttpUtil.ResponseWrap;

@Service
@Transactional
public class UserSpaceServiceImpl implements UserSpaceService {

	@Autowired
	private UserSpaceDao userSpaceDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private AppService appService;
	@Autowired
	private UserService userService;
	@Autowired
	private FileClient fileClient;
	@Autowired
	private TokenService tokenService ;
	@Autowired
	private PartnershipRecordDao partnershipRecordDao;
	@Autowired
	private SysDataToMallService sysService;

	private Logger logger = Logger.getLogger();

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public boolean save(UserSpace userSpace, UserSpaceDetail spaceDetail, Set<String> apps) {
		boolean isNew = false;
		// 详细资料
		UserSpaceDetail oldSpaceDetail = userSpaceDao.findByBusinessCode(spaceDetail.getBusinessCode());
		UserDetail adminDetail = new UserDetail(spaceDetail);
		if (oldSpaceDetail == null) {
			// 这里是通过其他应用直接注册
			if (!StringUtils.isEmpty(spaceDetail.getName())) {
				spaceDetail.setStatus(Status.ENABLED.value());
				if (null == spaceDetail.getRegisterDate()) {
					spaceDetail.setRegisterDate(new Date().getTime());
				}
				userSpaceDao.save(spaceDetail);
				logger.info(this.getClass(), spaceDetail.getBusinessCode(), "企业注册（来自接口）");
				oldSpaceDetail = spaceDetail;
				isNew = true;
			} else {
				throw new VisibleError("企业账户不存在，请先注册");
			}
		} else {
			BeanUtil.copyProperties(spaceDetail, oldSpaceDetail, true, "adminName", "adminTel", "adminEmail");
			if (!StringUtils.isEmpty(adminDetail.getMobile())) {
				// 未设置管理员的情况下，才覆盖管理员信息
				if (StringUtils.isEmpty(oldSpaceDetail.getAdminTel())) {
					oldSpaceDetail.setAdminName(adminDetail.getName());
					oldSpaceDetail.setAdminTel(adminDetail.getMobile());
					oldSpaceDetail.setAdminEmail(adminDetail.getEmail());
				}
			}
			userSpaceDao.save(oldSpaceDetail);
		}

		// 应用相关资料
		UserSpace oldOne = getExistUserSpace(userSpace);
		if (oldOne != null) {
			BeanUtil.copyProperties(userSpace, oldOne, true);
			if (userSpace.getId() != null) {
				// 只有在提供了ID的情况下，才能修改AppId和UID；
				// 同时，旗下的用户也一并修改AppId和spaceUID
				if (!userSpace.getAppId().equals(oldOne.getAppId()) || !userSpace.getUid().equals(oldOne.getUid())) {
					userDao.updateUserSpace(oldOne.getId(), userSpace.getAppId(), userSpace.getUid());
				}
			}
			logger.info(this.getClass(), oldSpaceDetail.getBusinessCode(), "修改企业信息，From: " + oldOne.getAppId(), oldSpaceDetail);
		} else {
			oldOne = userSpace;
			logger.info(this.getClass(), oldSpaceDetail.getBusinessCode(), "开通应用: " + oldOne.getAppId(), userSpace);
		}

		oldOne = userSpaceDao.save(oldOne);
		// 自动同步到其他App
		syncUserSpace(oldOne, oldSpaceDetail, apps);
		// 同步管理员信息
		App app = appService.findOne(oldOne.getAppId());
		User adminUser = new User(app, oldOne, adminDetail);
		userService.save(adminUser, adminDetail);
		// 从应用调用接口时，务必传dialectUID；否则视为并未开通过该应用
		if (isNew && null == oldOne.getDialectUID()) {
			applyApp(oldSpaceDetail.getBusinessCode(), oldOne.getAppId(), null, null);
		}
		return isNew;
	}

	private UserSpace getExistUserSpace(UserSpace userSpace) {
		UserSpace oldOne = null;
		if (userSpace.getUid() != null) {
			oldOne = findOne(userSpace.getAppId(), userSpace.getUid());
		}
		if (oldOne == null && userSpace.getId() != null) {
			oldOne = userSpaceDao.findOne(userSpace.getId());
		}
		return oldOne;
	}

	/**
	 * 同步企业信息
	 * 
	 * @param userSpace
	 * @param spaceDetail
	 * @param apps
	 */
	private void syncUserSpace(final UserSpace userSpace, final UserSpaceDetail spaceDetail, Set<String> apps) {
		final App app = appService.findOne(userSpace.getAppId());
		String copyApps = app.getCopyApps();
		// 未指定应用，按当前应用的配置来选择
		if (null == apps) {
			// 默认all表示全部
			if (StringUtils.isEmpty(copyApps) || App.COPY_ALL.equals(copyApps)) {
				apps = new HashSet<String>(appService.findAllIDs());
			} else {
				apps = new HashSet<String>(Arrays.asList(copyApps.split(App.COPY_APP_SPLIT)));
			}
		} else {
			// 指定了应用时，也要带上Copy属性指定的应用
			if (!StringUtils.isEmpty(copyApps) && !App.COPY_ALL.equals(copyApps)) {
				apps.addAll(Arrays.asList(copyApps.split(App.COPY_APP_SPLIT)));
			}
		}
		ExecuteUtils.execute(new ICallable<Void, String>() {

			@Override
			public Void call(String appId) throws Exception {
				App tempApp = appService.findOne(appId);
				// 不是级联应用（如商城，级联于平台）+ 配置了回调接口 + 属于PUBLIC作用域
				if (tempApp != null && !tempApp.getUid().equals(app.getUid()) && StringUtils.isEmpty(tempApp.getUserControl())
						&& !StringUtils.isEmpty(tempApp.getBackSpaceUrl()) && "PUBLIC".equals(tempApp.getScope())
						&& (Const.YES == tempApp.getDefaultUse())) {
					UserSpace tempS = new UserSpace();
					tempS.setUid(userSpace.getUid());
					tempS.setName(userSpace.getName());
					tempS.setAppId(tempApp.getUid());
					UserSpace oldOne = findOne(tempApp.getUid(), tempS.getUid());
					if (oldOne == null) {
						tempS.setId(null);
					} else {
						tempS.setId(oldOne.getId());
					}
					try {
						UserSpace backUserSpace = callbackToApp(tempApp, tempS, spaceDetail);
						if (backUserSpace != null) {
							tempS.setDialectUID(backUserSpace.getDialectUID());
						}
						userSpaceDao.save(tempS);
						logger.info(this.getClass(), spaceDetail.getBusinessCode(), String.format("同步企业信息，To: %s", tempApp.getUid()));
					} catch (Exception e) {
						logger.error(this.getClass(), spaceDetail.getBusinessCode(), String.format("同步企业信息，To: %s", tempApp.getUid()), e);
						userSpaceDao.saveFailed(new UserSpaceFailed(userSpace, tempS, e));
					}
				}
				return null;
			}
		}, apps);
	}

	@Override
	public UserSpace callbackToApp(App app, UserSpace userSpace, UserSpaceDetail userSpaceDetail) throws Exception {
		String url = app.getBackSpaceUrl();
		if (!StringUtils.isEmpty(url)) {
			JSONObject formData = JSON.parseObject(JSON.toJSONString(userSpace));
			formData.putAll(JSON.parseObject(JSON.toJSONString(userSpaceDetail)));
			ResponseWrap res = HttpUtil.doPost(url, formData, 300000);// 5分钟超时
			if (!res.isSuccess()) {
				throw new Exception(res.getContent());
			} else {
				return JSON.parseObject(res.getContent(), UserSpace.class);
			}
		}
		return null;
	}

	@Override
	@Cacheable("userspaces")
	public UserSpace findOne(String appId, String uid) {
		return userSpaceDao.findOne(appId, uid);
	}

	@Override
	@Cacheable("userspaces")
	public List<UserSpace> findByUID(String uid) {
		return userSpaceDao.findByUID(uid);
	}

	@Override
	@Cacheable("userspaces")
	public UserSpace findByDialectUID(String appId, String dialectUID){
		return userSpaceDao.findDialectOne(appId, dialectUID);
	}

	@Override
	@Cacheable("userspaces")
	public Page<UserSpace> findAll(String appId, int pageNumber, int pageSize) {
		return userSpaceDao.findAll(appId, pageNumber, pageSize);
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public UserSpaceDetail register(UserSpaceDetail userSpaceDetail) {
		UserSpaceDetail oldOne = findByName(userSpaceDetail.getName());
		if (oldOne != null && oldOne.getStatus().equals(Status.ENABLED.value())) {
			throw new VisibleError("企业名称已被注册！");
		}
		oldOne = findByBusinessCode(userSpaceDetail.getBusinessCode());
		if (oldOne != null && oldOne.getStatus().equals(Status.ENABLED.value())) {
			throw new VisibleError("营业执照号已被注册！");
		}
		// 对提交的验证码和手机号进行验证
		String checkcode = userSpaceDetail.getCheckcode();
		String checkcodeToken = userSpaceDetail.getCheckcodeToken();
		if (StringUtils.isEmpty(checkcodeToken)) {
			throw new VisibleError("请先获取验证码！");
		}
		if (StringUtils.isEmpty(checkcode)) {
			throw new VisibleError("请先输入验证码！");
		}
		Token existToken = tokenService.findOne(checkcodeToken);
		if (existToken == null || existToken.isExpired()) {
			throw new VisibleError("验证码已经失效，请重新获取");
		}
		if (!existToken.getTel().equals(userSpaceDetail.getAdminTel()) || !existToken.getEmail().equals(userSpaceDetail.getAdminEmail())){
			throw new VisibleError("请重新获取验证码");
		}
		String existCode = existToken.getBind().toString();
		if (!checkcode.equals(existCode)) {
			throw new VisibleError("验证码错误");
		}

		// 企业状态注册状态设为待激活
		// userSpaceDetail.setStatus(Status.UNACT.value());
		// 资料验证状态设为待验证
		// userSpaceDetail.setApproveStatus(Status.UNAPPROVED.value());
		// 不用验证状态，不设置待激活状态了
		userSpaceDetail.setRegisterDate(new Date().getTime());
		if (!StringUtils.isEmpty(userSpaceDetail.getUrl())) {
			userSpaceDetail.setUrl(StringUtils.trimAllWhitespace(userSpaceDetail.getUrl()));
			if (!userSpaceDetail.getUrl().toLowerCase().startsWith("http")) {
				userSpaceDetail.setUrl("http://" + userSpaceDetail.getUrl());
			}
		}
		if (StringUtils.isEmpty(userSpaceDetail.getArea())) {
			userSpaceDetail.setArea("中国大陆");
		}
		if (StringUtils.isEmpty(userSpaceDetail.getIndustry())) {
			userSpaceDetail.setIndustry("make");
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getFax())) {
			userSpaceDetail.setFax(StringUtils.trimAllWhitespace(userSpaceDetail.getFax()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getTel())) {
			userSpaceDetail.setTel(StringUtils.trimAllWhitespace(userSpaceDetail.getTel()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getAdminTel())) {
			userSpaceDetail.setAdminTel(StringUtils.trimAllWhitespace(userSpaceDetail.getAdminTel()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getAdminEmail())) {
			userSpaceDetail.setAdminEmail(StringUtils.trimAllWhitespace(userSpaceDetail.getAdminEmail()));
		}
		userSpaceDetail = userSpaceDao.save(userSpaceDetail);
		// 管理员
		userDao.save(new UserDetail(userSpaceDetail));
		logger.info(this.getClass(), userSpaceDetail.getBusinessCode(), "企业注册");
		return userSpaceDetail;
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public UserSpaceDetail registerByMobile(UserSpaceDetail userSpaceDetail) {
		userSpaceDetail.setStatus(Status.UNAUDIT.value());
		userSpaceDetail.setRegisterDate(new Date().getTime());
		if (!StringUtils.isEmpty(userSpaceDetail.getUrl())) {
			userSpaceDetail.setUrl(StringUtils.trimAllWhitespace(userSpaceDetail.getUrl()));
			if (!userSpaceDetail.getUrl().toLowerCase().startsWith("http")) {
				userSpaceDetail.setUrl("http://" + userSpaceDetail.getUrl());
			}
		}
		if (StringUtils.isEmpty(userSpaceDetail.getArea())) {
			userSpaceDetail.setArea("中国大陆");
		}
		if (StringUtils.isEmpty(userSpaceDetail.getIndustry())) {
			userSpaceDetail.setIndustry("make");
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getFax())) {
			userSpaceDetail.setFax(StringUtils.trimAllWhitespace(userSpaceDetail.getFax()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getTel())) {
			userSpaceDetail.setTel(StringUtils.trimAllWhitespace(userSpaceDetail.getTel()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getAdminTel())) {
			userSpaceDetail.setAdminTel(StringUtils.trimAllWhitespace(userSpaceDetail.getAdminTel()));
		}
		if (!StringUtils.isEmpty(userSpaceDetail.getAdminEmail())) {
			userSpaceDetail.setAdminEmail(StringUtils.trimAllWhitespace(userSpaceDetail.getAdminEmail()));
		}
		userSpaceDetail = userSpaceDao.save(userSpaceDetail);
		// 管理员
		userDao.save(new UserDetail(userSpaceDetail));
		logger.info(this.getClass(), userSpaceDetail.getName(), "企业注册(通过手机)");
		return userSpaceDetail;
	}

	@Override
	@Cacheable(value = "userspaces", key = "'businessCode:'+#businessCode")
	public UserSpaceDetail findByBusinessCode(String businessCode) {
		return userSpaceDao.findByBusinessCode(businessCode);
	}

	@Override
	@Cacheable(value = "userspaces", key = "'id:'+#id")
	public UserSpaceDetail findById(Long id) {
		return userSpaceDao.findById(id);
	}

	@Override
	@Cacheable(value = "userspaces", key = "'domain:'+#domain")
	public UserSpaceDetail findByDomain(String domain) {
		return userSpaceDao.findByDomain(domain);
	}

	@Override
	@Cacheable(value = "userspaces", key = "'name:'+#name")
	public UserSpaceDetail findByName(String name) {
		return userSpaceDao.findByName(name);
	}

	@Override
	public Page<UserSpaceDetailView> findAllUnActive(String name, String businessCode, int pageNumber, int pageSize) {
		return userSpaceDao.findAllView(pageNumber, pageSize, name, businessCode, Status.UNACT.value());
	}

	@Override
	public Page<UserSpaceDetailView> findAllEnable(String name, String businessCode, int pageNumber, int pageSize) {
		return userSpaceDao.findAllView(pageNumber, pageSize, name, businessCode, Status.ENABLED.value());
	}

	@Override
	public Page<UserSpaceDetailView> findAllUnAudit(String name, String businessCode, int pageNumber, int pageSize) {
		return userSpaceDao.findAllView(pageNumber, pageSize, name, businessCode, Status.UNAUDIT.value());
	}

	@Override
	public Page<UserSpaceDetailView> findAllUnApply(String name, String businessCode, int pageNumber, int pageSize) {
		return userSpaceDao.findAllView(pageNumber, pageSize, name, businessCode, Status.UNAPPLY.value());
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public UserSpaceDetail save(UserSpaceDetail userSpaceDetail) {
		return userSpaceDao.save(userSpaceDetail);
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public void delete(UserSpaceDetail userSpaceDetail) {
		UserSpaceDetail oldOne = findByBusinessCode(userSpaceDetail.getBusinessCode());
		if (oldOne != null) {
			if (Status.ENABLED.value() == oldOne.getStatus()) {
				throw new VisibleError("企业已激活，无法删除");
			}
			if (!StringUtils.isEmpty(oldOne.getBusinessCodeImage())) {
				fileClient.delete(oldOne.getBusinessCodeImage());
			}
			userSpaceDao.delete(userSpaceDetail);
		}
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public void enable(String businessCode) {
		UserSpaceDetail detail = findByBusinessCode(businessCode);
		if (detail != null) {
			detail.setStatus(Status.UNACT.value());
			userSpaceDao.save(detail);
			logger.info(this.getClass(), businessCode, "审批企业信息", "允许通过");
		} else {
			throw new VisibleError("找不到该企业资料");
		}
	}

	@Override
	@CacheEvict(value = "userspaces", allEntries = true)
	public void disable(Long id, String reason) {
		UserSpaceDetail detail = findById(id);
		if (detail != null) {
			detail.setStatus(Status.UNAPPLY.value());
			detail.setErrMsg(reason);
			userSpaceDao.save(detail);
			logger.info(this.getClass(), String.valueOf(id), "审批企业信息", reason);
		} else {
			throw new VisibleError("找不到该企业资料");
		}
	}

	@Override
	@CacheEvict(value = { "userspaces", "users", "userView" }, allEntries = true)
	public UserSpaceAndUserInfo initUserSpaceDetail(final UserSpaceDetail detail, final String adminPassword,
			final List<UserDetail> users) {
		final UserSpaceAndUserInfo info = new UserSpaceAndUserInfo();
		List<App> apps = appService.findAll();
		final UserDetail userDetail = new UserDetail(detail);
		detail.setStatus(Status.ENABLED.value());
		userSpaceDao.save(detail);
		if (!CollectionUtils.isEmpty(users)) {
			for (UserDetail det : users) {
				det = userDao.save(det);
			}
		}
		ExecuteUtils.execute(new ICallable<Void, App>() {

			@Override
			public Void call(App app) throws Exception {
				if (StringUtils.isEmpty(app.getUserControl())
						&& (!StringUtils.isEmpty(app.getBackSpaceUrl()) || !StringUtils.isEmpty(app.getBackUserUrl()))
						&& (Const.YES == app.getDefaultUse())) {
					if (!StringUtils.isEmpty(app.getBackSpaceUrl())) {
						UserSpace userSpace = new UserSpace(app, detail);
						try {
							userSpace = userSpaceDao.save(userSpace);
							UserSpace backUserSpace = callbackToApp(app, userSpace, detail);
							if (backUserSpace != null) {
								userSpace.setDialectUID(backUserSpace.getDialectUID());
								userSpace = userSpaceDao.save(userSpace);
								info.setSpaceDialectUID(userSpace.getDialectUID());
								logger.info(this.getClass(), detail.getBusinessCode(), "开通应用: " + app.getUid(), userSpace);
								sysService.UserSpace(userSpace, detail);
								User user = new User(app, userSpace, detail);
								user.setPassword(adminPassword);
								user = userDao.save(user);
								try {
									User backUser = userService.syncUserToApp(app, user, userDetail);
									if (backUser != null) {
										user.setDialectUID(backUser.getDialectUID());
										if (backUser.getAppId().equals("b2b")) {
											user.setSalt(backUser.getSalt());
											user.setPassword(userService.getEncryPassword(app.getEncryFormat(),
													adminPassword, backUser.getSalt()));
										} else if (backUser.getAppId().equals("im")) {
											user.setPassword(userService.getEncryPassword(app.getEncryFormat(),
													adminPassword, null));
										}
										// 不能调用userService的save()
										user = userDao.save(user);
										info.setUserDialectUID(user.getDialectUID());
										logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
										sysService.user(user);
										if (null != detail.getInviteuid() && null != detail.getInviteUserCode()) {
											addPartnershipRecord(detail, user);
										} else {
											addPartnershipList(detail, user);
										}
									}
								} catch (Exception e) {
									e.printStackTrace();
									userDao.saveFailed(new UserFailed(user, e));
								}
								if (!CollectionUtils.isEmpty(users)) {
									for (UserDetail det : users) {
										List<UserView> othUsers = userService.findByAppAndUID(app.getUid(), det.getMobile());
										user = new User(app, userSpace, det);
										if (!CollectionUtils.isEmpty(othUsers)) {
											// 同应用下，密码密文是一致的，可以直接设置
											user.setPassword(othUsers.get(0).getPassword());
											user.setDialectUID(othUsers.get(0).getDialectUID());
										}
										// 密码为空的用户会在首次登录的时候去设置密码
										user = userDao.save(user);
										try {
											User backUser = userService.syncUserToApp(app, user, det);
											if (backUser != null) {
												user.setDialectUID(backUser.getDialectUID());
												if (backUser.getAppId().equals("b2b")) {
													user.setSalt(backUser.getSalt());
												}
												// 不能调用userService的save()
												user = userDao.save(user);
												logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
											}
										} catch (Exception e) {
											e.printStackTrace();
											userDao.saveFailed(new UserFailed(user, e));
										}
									}
								}
							} else {
								logger.error(this.getClass(), detail.getBusinessCode(), "开通应用: " + app.getUid(), userSpace);
							}
						} catch (Exception e) {
							e.printStackTrace();
							logger.error(this.getClass(), detail.getBusinessCode(), "开通应用: " + app.getUid(), e);
							userSpaceDao.saveFailed(new UserSpaceFailed(userSpace, e));
						}
					} else {
						// 应用本身无需绑定企业
						User user = new User(app, detail);
						user.setPassword(adminPassword);
						userDao.save(user);// save or update
						try {
							User backUser = userService.syncUserToApp(app, user, userDetail);
							if (backUser != null) {
								user.setDialectUID(backUser.getDialectUID());
								user.setPassword(
										userService.getEncryPassword(app.getEncryFormat(), adminPassword, null));
								// 不能调用userService的save()
								userDao.save(user);
								logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
							}
						} catch (Exception e) {
							e.printStackTrace();
							userDao.saveFailed(new UserFailed(user, e));
						}
						if (!CollectionUtils.isEmpty(users)) {
							for (UserDetail det : users) {
								user = new User(app, det);
								userService.setPasswordBySameApp(app, user, det);
								user = userDao.save(user);
								try {
									User backUser = userService.syncUserToApp(app, user, det);
									if (backUser != null) {
										user.setDialectUID(backUser.getDialectUID());
										user.setPassword(userService.getEncryPassword(app.getEncryFormat(),
												adminPassword, null));
										// 不能调用userService的save()
										user = userDao.save(user);
										logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
									}
								} catch (Exception e) {
									e.printStackTrace();
									userDao.saveFailed(new UserFailed(user, e));
								}
							}
						}
					}
				}
				return null;
			}
		}, apps);
		return info;
	}

	/**
	 * 如果是从邀请链接注册，自动添加合作关系并是已同意状态
	 * 
	 * @param detail
	 * @param user
	 */
	private void addPartnershipRecord(UserSpaceDetail detail, User user) {
		PartnershipRecord record = new PartnershipRecord();
		UserSpaceDetail spaceDetail = userSpaceDao.findByBusinessCode(detail.getInviteuid());
		List<User> userInfos = userDao.findByDialectUID(detail.getInviteUserCode());
		User userInfo = new User();
		if (!CollectionUtils.isEmpty(userInfos)) {
			userInfo = userInfos.get(0);
		}
		record.setAppId(AccountConfig.ACCOUNT_CENTER);
		record.setCustName(spaceDetail.getName());
		record.setCustUID(spaceDetail.getBusinessCode());
		record.setCustUserCode(userInfo.getDialectUID());
		record.setCustUserEmail(userInfo.getSecondUID());
		record.setCustUserName(userInfo.getName());
		record.setCustUserTel(userInfo.getUid());
		record.setOperateDate(new Date());
		record.setRequestDate(new Date());
		record.setStatus(Status.ENABLED.getPhrase());
		record.setStatusCode(Status.ENABLED.value());
		record.setVendName(detail.getName());
		record.setVendUID(detail.getBusinessCode());
		record.setVendUserCode(user.getDialectUID());
		record.setVendUserEmail(user.getSecondUID());
		record.setVendUserName(user.getName());
		record.setVendUserTel(user.getUid());
		record.setMethod(detail.getMethod());
		try {
			partnershipRecordDao.save(record);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if ("addVendor".equals(record.getMethod())) {
			// 同步到平台生成供应商关系，并且设置同步到ERP状态为待下载
			try {
				synchroToPlatform(record);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void synchroToPlatform(PartnershipRecord record) throws Exception {
		App app = appService.findOne("b2b");
		String url = app.getBackPartnerUrl();
		if (!StringUtils.isEmpty(url)) {
			//时间不需要
			record.setRequestDate(null);
			record.setOperateDate(null);
			JSONObject formData = JSON.parseObject(JSON.toJSONString(record));
			ResponseWrap res = HttpUtil.doPost(url, formData, 30000);
			if (!res.isSuccess()) {
				logger.error("同步合作伙关系失败", "cust：" + record.getCustUID() + ",vend：" + record.getVendUID());
			} else {
				logger.info("同步合作伙关系", "cust：" + record.getCustUID() + ",vend：" + record.getVendUID());
			}
		}

	}

	/**
	 * 批量模糊建立合作关系（这个不是精确添加，数据不会很准确）
	 * 
	 * @param detail
	 * @param user
	 */
	private void addPartnershipList(UserSpaceDetail detail, User user) {
		List<InvitationRecord> records = partnershipRecordDao.findByVendname(detail.getName());
		if (!CollectionUtils.isEmpty(records)) {
			for (InvitationRecord record : records) {
				detail.setInviteuid(record.getBussinesscode());
				detail.setInviteUserCode(String.valueOf(record.getUseruu()));
				if ("erp".equals(record.getSource())) {
					detail.setMethod("addVendor");
				}
				addPartnershipRecord(detail, user);
			}
		}
	}

	@Override
	@CacheEvict(value = { "userspaces", "users", "userView" }, allEntries = true)
	public void applyApp(String businessCode, String appId, String adminPassword, final List<UserDetail> users) {
		if (!CollectionUtils.isEmpty(users)) {
			for (UserDetail det : users) {
				userDao.save(det);
			}
		}
		UserSpaceDetail detail = findByBusinessCode(businessCode);
		App app = appService.findOne(appId);
		if (detail != null && app != null && !StringUtils.isEmpty(app.getBackSpaceUrl())) {
			UserSpace userSpace = findOne(appId, businessCode);
			if (userSpace == null) {
				userSpace = userSpaceDao.save(new UserSpace(app, detail));
			}
			try {
				UserSpace backUserSpace = callbackToApp(app, userSpace, detail);
				if (backUserSpace != null) {
					userSpace.setDialectUID(backUserSpace.getDialectUID());
					userSpace = userSpaceDao.save(userSpace);
					logger.info(this.getClass(), detail.getBusinessCode(), "开通应用: " + app.getUid(), userSpace);
					// 同步企业数据到商城
                    sysService.UserSpace(userSpace, detail);
					if (!StringUtils.isEmpty(app.getBackUserUrl())) {
						UserDetail userDetail = userService.findOne(detail.getAdminTel());
						if (userDetail == null) {
							userDetail = new UserDetail(detail);
							detail.setStatus(Status.ENABLED.value());
							userSpaceDao.save(detail);
						}
						User user = userService.findOne(appId, userSpace.getUid(), detail.getAdminTel());
						user = null == user ? new User(app, userSpace, detail) : user;
						if (null == user.getId()) {// is new
							if (!StringUtils.isEmpty(adminPassword)) {
								user.setPassword(adminPassword);
							} else {
								List<UserView> othUsers = userService.findByAppAndUID(appId, user.getUid());
								if (!CollectionUtils.isEmpty(othUsers)) {
									// 同应用下，密码密文是一致的，可以直接设置
									user.setPassword(othUsers.get(0).getPassword());
									user.setDialectUID(othUsers.get(0).getDialectUID());
								}
							}
							user = userDao.save(user);
							try {
								User backUser = userService.syncUserToApp(app, user, userDetail);
								if (backUser != null) {
									if (!StringUtils.isEmpty(adminPassword)) {
										if (adminPassword.length() < 32) {// 明文
											user.setPassword(userService.getEncryPassword(app.getEncryFormat(),
													adminPassword, backUser.getSalt()));
										} else {// 直接赋值以前的密码
											user.setPassword(adminPassword);
										}
									}
									user.setDialectUID(backUser.getDialectUID());
									user.setSalt(backUser.getSalt());
									// 不能调用userService的save()
									user = userDao.save(user);
									logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
									// 同步人员信息到商城
                                    sysService.user(backUser);
								}
							} catch (Exception e) {
								e.printStackTrace();
								userDao.saveFailed(new UserFailed(user, e));
							}
						} else {// 之前开通时调用子应用接口失败，账户中心有对照关系，而子应用里面还没有的情况下
							user.setSpaceId(userSpace.getId());
							user.setSpaceDialectUID(userSpace.getDialectUID());
							user = userDao.save(user);
							if (StringUtils.isEmpty(user.getDialectUID())) {
								try {
									User backUser = userService.syncUserToApp(app, user, userDetail);
									if (backUser != null) {
										if (user.getPassword().length() < 32) {
											user.setPassword(userService.getEncryPassword(app.getEncryFormat(), user.getPassword(),
													backUser.getSalt()));
										}
										user.setDialectUID(backUser.getDialectUID());
										user.setSalt(backUser.getSalt());
										user = userDao.save(user);
                                        // 同步人员信息到商城
                                        sysService.user(backUser);
									}
								} catch (Exception e) {
									e.printStackTrace();
									userDao.saveFailed(new UserFailed(user, e));
								}
							}
						}
						if (!CollectionUtils.isEmpty(users)) {
							for (UserDetail det : users) {
								user = userService.findOne(appId, userSpace.getUid(), det.getMobile());
								user = null == user ? new User(app, userSpace, det) : user;
								if (null == user.getId()) {// is new
									List<UserView> othUsers = userService.findByAppAndUID(app.getUid(), det.getMobile());
									if (!CollectionUtils.isEmpty(othUsers)) {
										// 同应用下，密码密文是一致的，可以直接设置
										user.setPassword(othUsers.get(0).getPassword());
										user.setDialectUID(othUsers.get(0).getDialectUID());
									}
									if (user.getPassword() == null) {
										user.setPassword("111111");
									}
									user = userDao.save(user);
									try {
										User backUser = userService.syncUserToApp(app, user, det);
										if (backUser != null) {
											user.setDialectUID(backUser.getDialectUID());
											user.setSalt(backUser.getSalt());
											if (null != backUser.getPassword())
												user.setPassword(backUser.getPassword());
											// 不能调用userService的save()
											user = userDao.save(user);
											logger.info(this.getClass(), detail.getBusinessCode(), "创建用户: " + user.getUid(), user);
                                            // 同步人员信息到商城
                                            sysService.user(backUser);
										}
									} catch (Exception e) {
										e.printStackTrace();
										userDao.saveFailed(new UserFailed(user, e));
									}
								} else {// 之前开通时调用子应用接口失败，账户中心有对照关系，而子应用里面还没有的情况下
									user.setSpaceId(userSpace.getId());
									user.setSpaceDialectUID(userSpace.getDialectUID());
									user = userDao.save(user);
									// 去掉这个条件语句，因为存在同用户多组织情况，目前程序必须得sync多次
									// if
									// (StringUtils.isEmpty(user.getDialectUID()))
									// {}
									try {
										User backUser = userService.syncUserToApp(app, user, det);
										if (backUser != null) {
											if (user.getPassword().length() < 32) {
												user.setPassword(userService.getEncryPassword(app.getEncryFormat(), user.getPassword(),
														backUser.getSalt()));
											}
											user.setDialectUID(backUser.getDialectUID());
											user.setSalt(backUser.getSalt());
											user = userDao.save(user);
                                            // 同步人员信息到商城
                                            sysService.user(backUser);
										}
									} catch (Exception e) {
										e.printStackTrace();
										userDao.saveFailed(new UserFailed(user, e));
									}
								}
							}
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
				logger.error(this.getClass(), detail.getBusinessCode(), "开通应用: " + app.getUid(), e);
				userSpaceDao.saveFailed(new UserSpaceFailed(userSpace, e));
			}
		}
	}

	@Override
	public ModelMap getUserSpaceAppCount() {
		ModelMap map = new ModelMap("全部", userSpaceDao.getUserSpaceDetailCount());
		map.addAllAttributes(userSpaceDao.getUserSpaceAppCount());
		return map;
	}

	@Override
	public void enable(Long id) {
		UserSpaceDetail detail = findById(id);
		if (detail != null) {
			detail.setStatus(Status.UNACT.value());
			userSpaceDao.save(detail);
			logger.info(this.getClass(), detail.getBusinessCode(), "审批企业信息", "允许通过");
		} else {
			throw new VisibleError("找不到该企业资料");
		}
	}

	@Override
	public Page<UserSpaceDetailView> findAll(String name, String businessCode, String address, int pageNumber, int pageSize) {
		return userSpaceDao.findAllView(pageNumber, pageSize, name, businessCode, address);
	}

	@Override
	public Page<UserSpaceDetail> findByKeyword(String keyword, int pageNumber, int pageSize) {
		return userSpaceDao.findByKeyword(keyword, pageNumber, pageSize);
	}

	@Override
	public void delete(UserSpace userSpace) {
		userSpace = getExistUserSpace(userSpace);
		if (null != userSpace) {
			userService.deleteByAppAndSpace(userSpace.getAppId(), userSpace.getId());
			userSpaceDao.delete(userSpace);
		}
	}

	@Override
	public List<UserSpaceDetail> findAll(String ids) {
		List<Long> idList = JSONObject.parseArray(ids, Long.class);
		if (!CollectionUtils.isEmpty(idList))
			return userSpaceDao.findAll(idList);
		return Collections.emptyList();
	}

	@Override
	public String callbacktoAppAfterUpdate(App app, UserSpaceDetail detail) throws Exception {
		String url = app.getBackSpaceUrl();
		url = url + "/renewUserSpace";
		if (!StringUtils.isEmpty(url)) {
			JSONObject formData = JSON.parseObject(JSON.toJSONString(detail));
			ResponseWrap res = HttpUtil.doPost(url, formData, 300000);// 5分钟超时
			if (!res.isSuccess())
				throw new Exception(res.getContent());
			else
				return res.getContent();
		}
		return null;
	}

	@Override
	public List<UserSpaceDetailInfo> findByTel(List<String> tels) {
		return userSpaceDao.findByTel(tels);
	}

	@Override
	public List<UserSpaceDetailInfo> findUserByTel(List<String> tels) {
		return userSpaceDao.findUserByTel(tels);
	}

	@Override
	public List<UserSpaceDetailInfo> findByKeyword(String keyword, Integer pageNumber) {
		return userSpaceDao.findByKeyword(keyword, pageNumber);
	}

	@Override
	public void saveUserSpace(UserSpace space) {
		userSpaceDao.save(space);
	}

	@Override
	public void update(UserSpace space, Long id) {
		userSpaceDao.update(space, id);
	}

}
