package cn.myapps.runtime.user.controller;

import static com.jayway.jsonpath.JsonPath.parse;

import java.util.*;

import cn.myapps.authtime.user.model.UserVO;
import cn.myapps.authtime.user.service.UserProcess;
import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.data.tree.UserNode;
import com.bcxin.saas.domains.dtos.PageResultDto;
import com.bcxin.saas.domains.dtos.PageSearchDto;
import com.bcxin.saas.domains.readers.EmployeeDbReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;

import cn.myapps.authtime.common.service.AuthTimeServiceManager;
import cn.myapps.authtime.user.service.UserRunTimeService;
import cn.myapps.authtime.usergroup.model.UserGroupVO;
import cn.myapps.authtime.usergroup.service.UserGroupProcess;
import cn.myapps.authtime.usergroup.service.UserGroupSetProcess;
import cn.myapps.base.web.WebUser;
import cn.myapps.base.web.listener.OnlineUsers;
import cn.myapps.common.auth.IUser;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.data.DataPackage;
import cn.myapps.runtime.common.controller.AbstractRuntimeController;
import cn.myapps.util.ProcessFactory;
import cn.myapps.util.StringUtil;
import cn.myapps.util.sequence.Sequence;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户选择框
 *
 * @author spy
 *
 */
@Api(tags = "用户选择框执行模块")
@Component
@RequestMapping(path = "/api/runtime", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class UserSelectboxController extends AbstractRuntimeController{

	@Autowired
	private UserRunTimeService userService;

	@Autowired
	private EmployeeDbReader employeeDbReader;

	/**
	 * 获取以部门为树形结构的用户集合
	 * @param applicationId 软件id
	 * @param deptId 部门id
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/{applicationId}/users/selectbox/department")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取以部门为树形结构的用户集合", notes = "获取以部门为树形结构的用户集合")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "deptId",value = "部门id",required = true,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = false,paramType = "query",dataType = "string",defaultValue="10"),
			@ApiImplicitParam(name = "pageNum",value = "当前页",required = false,paramType = "query",dataType = "string",defaultValue="1")
	})
	public Resource getUserListAsDeptTree(
			@PathVariable String applicationId,
			@RequestParam(required = false,name = "deptId") String deptId,
			@RequestParam(required=false,defaultValue="10") String pageSize, @RequestParam(required=false,defaultValue="1") String pageNum) throws Exception{
		if (pageSize == null || "".equals(pageSize) || "null".equals(pageSize)) {
			pageSize = "10";
		}
		if (pageNum == null || "".equals(pageNum) || "null".equals(pageNum)) {
			pageNum = "1";
		}
		int newPageSize = Integer.parseInt(pageSize);
		int newPageNum = Integer.parseInt(pageNum);
		PageSearchDto searchDto = new PageSearchDto();
		searchDto.setDomainId(getUser().getDomainid());
		searchDto.setDeptId(deptId);
		searchDto.setPageNum(newPageNum);
		searchDto.setPageSize(newPageSize);

		PageResultDto result = employeeDbReader.getEmployeeByDepartId(searchDto);
//		Map<String, Object> result = userService.getUserListAsDeptTree(getUser(), deptId, applicationId, newPageNum, newPageSize);
		return success("ok", result);
	}

	/**
	 * 获取以角色为树形结构的用户集合(分页)
	 * @param applicationId
	 * 		软件id
	 * @param roleId
	 * 		角色id
	 * @param pageSize
	 * 		每页显示数据数
	 * @param pageNum
	 * 		当前页
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/{applicationId}/users/selectbox/role")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取以角色为树形结构的用户集合(分页)", notes = "获取以角色为树形结构的用户集合(分页)")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "roleId",value = "角色id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = false,paramType = "query",dataType = "string",defaultValue="10"),
			@ApiImplicitParam(name = "pageNum",value = "当前页",required = false,paramType = "query",dataType = "string",defaultValue="1")
	})
	public Resource getUserListAsRoleTree(@PathVariable String applicationId, @RequestParam(required=false) String roleId, @RequestParam(required=false,defaultValue="10") String pageSize, @RequestParam(required=false,defaultValue="1") String pageNum) throws Exception{
		if (pageSize == null || "".equals(pageSize) || "null".equals(pageSize)) {
			pageSize = "10";
		}
		if (pageNum == null || "".equals(pageNum) || "null".equals(pageNum)) {
			pageNum = "1";
		}
		int newPageSize = Integer.parseInt(pageSize);
		int newPageNum = Integer.parseInt(pageNum);
		ParamsTable params = getParams();
		String flowId = params.getParameterAsString("flowId");
		String nodeId = params.getParameterAsString("nodeId");
		String docId = params.getParameterAsString("docId");
		int type  = params.getParameterAsInteger("type");

		if (!StringUtil.isBlank(roleId)) { // 获取角色下的成员
			PageSearchDto searchDto = new PageSearchDto();
			searchDto.setDomainId(getUser().getDomainid());
			searchDto.setRoleId(roleId);
			searchDto.setPageNum(newPageNum);
			searchDto.setPageSize(newPageSize);

			PageResultDto result = employeeDbReader.getEmployees(searchDto);
			return success("ok", result);
		}

		Map<String, Object> result = userService.getUserListAsRoleTree(getUser(), roleId, flowId,nodeId,applicationId,docId, newPageSize, newPageNum,type,request);
		return success("ok", result);
	}

	/**
	 * 获取以通讯录为树形结构的用户集合
	 * @param pageNum 每页数
	 * @param pageSize 每页显示数据数
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/users/selectbox/contacts")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取以通讯录为树形结构的用户集合", notes = "获取以通讯录为树形结构的用户集合")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "contactsId",value = "通讯录分组id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "userName",value = "用户名称",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "pageNum",value = "每页数",required = false,paramType = "query",dataType = "string",defaultValue="1"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = false,paramType = "query",dataType = "string",defaultValue="10"),
			@ApiImplicitParam(name = "isFromMail",value = "是否邮件调用",required = false,paramType = "query",dataType = "string")
	})
	public Resource getUserListAsContactsTree(@RequestParam(required=false) String contactsId, @RequestParam(required=false) String userName, @RequestParam(required=false,defaultValue="1") String pageNum, @RequestParam(required=false,defaultValue="10") String pageSize, @RequestParam(required = false) boolean isFromMail) throws Exception{

		if (pageSize == null || "".equals(pageSize) || "null".equals(pageSize)) {
			pageSize = "10";
		}
		if (pageNum == null || "".equals(pageNum) || "null".equals(pageNum)) {
			pageNum = "1";
		}
		int newPageSize = Integer.parseInt(pageSize);
		int newPageNum = Integer.parseInt(pageNum);

		PageSearchDto searchDto = new PageSearchDto();
		searchDto.setDomainId(getUser().getDomainid());
		searchDto.setContanctsId(contactsId);
		searchDto.setUserName(userName);
		searchDto.setFromMail(isFromMail);
		searchDto.setPageNum(newPageNum);
		searchDto.setPageSize(newPageSize);

		PageResultDto result = employeeDbReader.getEmployeeByDomainId(searchDto);
//		Map<String, Object> result = userService.getUserListAsContactsTree(contactsId, userName, isFromMail, getUser(), getParams(), pageNum, pageSize);
		return success("ok", result);
	}

	/**
	 * 更新在线用户
	 */
	@PutMapping("/updateOnlineUsers")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "更新在线用户", notes = "更新在线用户")
	public void updateOnlineUsers(){
		try{
			WebUser user = AuthTimeServiceManager.getWebUser(request);
			//增加在线用户
			OnlineUsers.add(Sequence.getTimeSequence(),user);
		}catch (Exception e){
			e.printStackTrace();
		}

	}

	/**
	 * 移除在线用户
	 */
	@DeleteMapping("/removeOnlineUser")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "移除在线用户", notes = "移除在线用户")
	public void removeOnlineUser(HttpServletRequest request) {
		try {
			String userId = WebUser.getWebUserId(request);
			if (StringUtils.hasLength(userId)) {
				OnlineUsers.removeByUserId(userId);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 获取在线用户集合
	 * @param pageNum 当前页
	 * @param pageSize 每页显示条数
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/users/selectbox/onlines")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取在线用户集合", notes = "获取在线用户集合")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pageNum",value = "每页数",required = false,paramType = "query",dataType = "string",defaultValue="1"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = false,paramType = "query",dataType = "string",defaultValue="10")
	})
	public Resource getOnlineUserList(@RequestParam(required=false,defaultValue="1") String pageNum, @RequestParam(required=false,defaultValue="10") String pageSize) throws Exception{
		Map<String, Object> result = userService.getOnlineUserList(pageNum, pageSize, getUser());
		return success("ok", result);
	}

	@GetMapping(value = "/users/selectbox/dimissions")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取离职用户集合", notes = "获取离职用户集合")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pageNum",value = "每页数",required = true,paramType = "query",dataType = "string",defaultValue="1"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = true,paramType = "query",dataType = "string",defaultValue="50"),
			@ApiImplicitParam(name = "domainId",value = "企业域id",required = true,paramType = "query",dataType = "string")
	})
	public Resource getDismissionUserList(@RequestParam(required = true) String domainId,
										  @RequestParam(required = true) int pageNum,
										  @RequestParam(required = true) int pageSize){
		try {
			UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
			DataPackage<UserVO> dataPackage = userProcess.doQueryByDoaminaAndStatusAndPermissionType(domainId, "public",
					0, pageNum, pageSize);
			Collection<UserVO> datas = dataPackage.getDatas();
			List<UserNode> userNodes = new ArrayList<>();
			for (Iterator<UserVO> iterator = datas.iterator();iterator.hasNext();){
				UserVO userVO = iterator.next();
				UserNode u = new UserNode();
				u.setId(userVO.getId());
				u.setName(userVO.getName());
				userNodes.add(u);
			}
			return success("ok",userNodes);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 根据联系人姓名,首字母,电话进行模糊查询（联系人）
	 * @param keyWord 关键字
	 * @param pageSize 每页显示条数
	 * @param pageNum 当前页
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/users/selectbox/search")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "模糊查询用户", notes = "模糊查询用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "keyWord",value = "关键字",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "pageNum",value = "每页数",required = false,paramType = "query",dataType = "string",defaultValue="1"),
			@ApiImplicitParam(name = "pageSize",value = "每页显示数据数",required = false,paramType = "query",dataType = "string",defaultValue="10"),
			@ApiImplicitParam(name = "isFromMail",value = "是否邮件调用",required = false,paramType = "query",dataType = "string")
	})
	public Resource getUsersBySearch(@RequestParam(required=false) String keyWord, @RequestParam(required=false,defaultValue="10") String pageSize, @RequestParam(required=false,defaultValue="1") String pageNum, @RequestParam(required = false) boolean isFromMail) throws Exception{
		int pageNo = StringUtil.isBlank(pageNum) ? 1 : Integer.valueOf(pageNum);
		int pageCount = StringUtil.isBlank(pageSize) ? 10 : Integer.valueOf(pageSize);

		PageSearchDto searchDto = new PageSearchDto();
		searchDto.setDomainId(getUser().getDomainid());
		searchDto.setPageNum(pageNo);
		searchDto.setPageSize(pageCount);
		searchDto.setFromMail(isFromMail);
		searchDto.setKeyWord(keyWord);

		PageResultDto result = employeeDbReader.getEmployeeByDomainId(searchDto);

//		Map<String, Object> result = userService.getUsersBySearch(getUser(), keyWord, isFromMail, pageCount, pageNo);
		return success("ok", result);
	}

	/**
	 * 获取部门树
	 * @param parentId
	 * 		父级id
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/users/selectbox/dept-tree")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取部门树", notes = "获取部门树")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "parentId",value = "父级id",required = false,paramType = "query",dataType = "string")
	})
	public List<cn.myapps.runtime.dynaform.view.tree.Node> getDepartTree(@RequestParam(required=false) String parentId) throws Exception {
		List<cn.myapps.runtime.dynaform.view.tree.Node> result = userService.getDepartTree(parentId,getUser().getDomainid());
		return result;
	}

	/**
	 * 获取通讯录分组
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/users/selectbox/contacts/group")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取通讯录分组", notes = "获取通讯录分组")
	public Resource getContactsGroup() throws Exception {
		DataPackage<UserGroupVO> result = userService.getContactsGroup(getUser());
		return success("ok", result);
	}

	/**
	 * 新建通讯录分组
	 * @param name
	 * 		分组名称
	 * @throws Exception
	 */
	@PostMapping("/users/contacts/groups")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "新建通讯录分组", notes = "新建通讯录分组")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "name", value = "分组名称", required = true, paramType = "query", dataType = "string")})
	public Resource newContactsGroup(@RequestParam String name) throws Exception {
		IUser user = getUser();
		UserGroupProcess process = (UserGroupProcess) ProcessFactory.createProcess(UserGroupProcess.class);
		if(!process.isExistGroup(name, user.getId())){
			UserGroupVO userGroupVO = new UserGroupVO();
			userGroupVO.setName(name);
			userGroupVO.setOwnerId(user.getId());
			userGroupVO.setDomainid(user.getDomainid());
			process.doCreate(userGroupVO);
			return success("ok", userGroupVO);
		} else {
			return error(4001, "该分组名称已存在", null);
		}
	}

	/**
	 * 保存通讯录分组
	 * @param groupId
	 * 		分组id
	 * @param name
	 * 		分组名称
	 * @throws Exception
	 */
	@PostMapping("/users/contacts/groups/{groupId}")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "保存通讯录分组", notes = "保存通讯录分组")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "groupId", value = "分组id", required = true, paramType = "path", dataType = "string"),
			@ApiImplicitParam(name = "name", value = "分组名称", required = true, paramType = "query", dataType = "string")})
	public Resource saveContactsGroup(@PathVariable String groupId, @RequestParam String name) throws Exception {
		IUser user = getUser();
		UserGroupProcess process = (UserGroupProcess) ProcessFactory.createProcess(UserGroupProcess.class);
		UserGroupVO userGroupVO = (UserGroupVO) process.doView(groupId);
		if(process.isExistGroup(name, user.getId()) && !name.equals(userGroupVO.getName())){
			return error(4001, "该分组名称已存在", null);
		} else {
			userGroupVO.setName(name);
			userGroupVO.setOwnerId(user.getId());
			userGroupVO.setDomainid(user.getDomainid());
			process.doUpdate(userGroupVO);
			return success("ok", userGroupVO);
		}
	}

	/**
	 * 删除通讯录分组
	 * @param groupId
	 * 		分组id
	 * @throws Exception
	 */
	@DeleteMapping("/users/contacts/groups/{groupId}")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "删除通讯录分组", notes = "删除通讯录分组")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "groupId", value = "分组id", required = true, paramType = "path", dataType = "string")})
	public Resource removeContactsGroup(@PathVariable String groupId) throws Exception {
		UserGroupProcess process = (UserGroupProcess) ProcessFactory.createProcess(UserGroupProcess.class);
		process.doRemove(groupId);
		return success("ok", "删除成功");
	}

	/**
	 * 添加用户至通讯录分组
	 * @param groupId
	 * 		分组id
	 * @param userIds
	 * 		用户id集合
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/users/contacts/groups/{groupId}/users")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "添加用户至通讯录分组", notes = "添加用户至通讯录分组")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "groupId", value = "分组id", required = true, paramType = "path", dataType = "string"),
			@ApiImplicitParam(name = "userIds", value = "用户id集合", required = true, paramType = "body", dataType = "string")})
	public Resource addUserToContactsGroup(@PathVariable String groupId, @RequestBody String userIds) throws Exception {
		List<String> ids = parse(userIds).json();
		String[] idArray = {};
		idArray = ids.toArray(idArray);

		UserGroupSetProcess userGroupSetProcess = (UserGroupSetProcess) ProcessFactory.createProcess(UserGroupSetProcess.class);
		userGroupSetProcess.addUserToGroup(idArray, groupId);
		return success("ok", "添加成功");
	}

	/**
	 * 移除通讯录分组用户
	 * @param groupId
	 * 		分组id
	 * @param userIds
	 * 		用户id集合
	 * @return
	 * @throws Exception
	 */
	@DeleteMapping("/users/contacts/groups/{groupId}/users")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "移除通讯录分组用户", notes = "移除通讯录分组用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "groupId", value = "分组id", required = true, paramType = "path", dataType = "string"),
			@ApiImplicitParam(name = "userIds", value = "用户id集合", required = true, paramType = "body", dataType = "string")})
	public Resource removeUserFromContactsGroup(@PathVariable String groupId, @RequestBody String userIds) throws Exception {
		List<String> ids = parse(userIds).json();
		String[] idArray = {};
		idArray = ids.toArray(idArray);

		UserGroupSetProcess userGroupSetProcess = (UserGroupSetProcess) ProcessFactory.createProcess(UserGroupSetProcess.class);
		userGroupSetProcess.deleteByUser(idArray, groupId);
		return success("ok", "移除成功");
	}
}
