package cn.myapps.runtime.user.controller;

import cn.myapps.authtime.common.service.AuthTimeServiceManager;
import cn.myapps.authtime.user.MyProfileHelper;
import cn.myapps.authtime.user.model.UserVO;
import cn.myapps.authtime.user.service.UserProcess;
import cn.myapps.base.web.WebUser;
import cn.myapps.common.auth.IUser;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.data.tree.UserNode;
import cn.myapps.common.util.Security;
import cn.myapps.common.util.StringUtil;
import cn.myapps.runtime.common.controller.AbstractRuntimeController;
import cn.myapps.util.json.JsonTmpUtil;
import cn.myapps.util.sequence.Sequence;
import com.bcxin.saas.core.components.DistributedCacheProvider;
import com.bcxin.saas.core.exceptions.SaasBadException;
import com.bcxin.saas.core.exceptions.SaasNofoundException;
import com.bcxin.saas.core.utils.encrypt.PasswordUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by Seven on 2017/11/14.
 */
@Api(tags = "用户选择框执行模块")
@Component
@RequestMapping(path = "/api/runtime/users", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class UserController extends AbstractRuntimeController {

	private final DistributedCacheProvider distributedCacheProvider;

	public UserController(DistributedCacheProvider distributedCacheProvider) {
		this.distributedCacheProvider = distributedCacheProvider;
	}

	/**
     * 获取个人信息
     */
    @GetMapping("/myprofile")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取个人信息", notes = "获取个人信息")
    public Resource getLoginUser() throws Exception {
		//在其重定向时重新设置缓存中的user对象，每次登录时做,解决authtime改变用户信息时前台登录信息没有变化
		WebUser webUser = AuthTimeServiceManager.getWebUser(request);
		if (webUser == null) {
			UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
			UserVO user = (UserVO) userProcess.doView(webUser.getId());
			webUser = new WebUser(user);
			WebUser.setWebUser(webUser, request);
		}
		UserNode u = MyProfileHelper.buildProfile(webUser);
		return success("ok", u);
	}
    
    /**
     * 获取用户信息
     */
    @GetMapping("/profile")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取用户信息", notes = "获取用户信息")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id",value = "用户id",required = true,paramType = "query",dataType = "string")
	})
    public Resource getSelectUser(@RequestParam(required=false) String id) throws Exception{
    	UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
    	UserVO serVO = (UserVO) userProcess.doView(id);
    	WebUser webUser = new WebUser(serVO);
    	UserNode u = MyProfileHelper.buildProfile(webUser);
        return success("ok", u);
    }

	/**
	 * 获取用户头像
	 */
	@GetMapping("/{id}/avatar")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取用户头像", notes = "获取用户头像")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id",value = "用户id",required = true,paramType = "path",dataType = "string")
	})
	public Resource getSelectUserAvatar(@PathVariable String id) throws Exception{
		UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
		UserVO serVO = (UserVO) userProcess.doView(id);
		if(serVO != null){
			return success("ok", serVO.getAvatarUri());
		} else {
			return error(500, "用户不存在！", null);
		}
	}

    /**
     * 更新皮肤
     * @param jsonStr 请求包体
     * @return
     * @throws Exception
     */
    @PostMapping("/skin")
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "更新皮肤", notes = "更新皮肤")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "jsonStr",value = "请求包体",required = true,paramType = "body",dataType = "string")
	})
    public Resource setUserSkin(@RequestBody String jsonStr) throws Exception{
    	WebUser user = getUser();

        JSONObject jsonObject = JSONObject.fromObject(jsonStr);
        String skin = jsonObject.getString("skin");
        
        UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
		UserVO userVO = (UserVO) userProcess.doView(user.getId());

		userVO.setUserSkin(skin);

		userProcess.doPersonalUpdate(userVO);
        return success("ok", null);
    }
	
	/**
     * 前台解锁
     */
    @PutMapping("/unlock")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "前台解锁", notes = "前台解锁")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pwd",value = "请求包体",required = true,paramType = "body",dataType = "string")
	})
    public Resource validatePassword(@RequestBody String pwd) throws Exception{
        UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
		UserVO userVO = (UserVO) userProcess.doView(getUser().getId());
		if(PasswordUtils.isMatched(userVO.getLoginpwd(), pwd)){
			return success("ok", true);
		}
        return success("ok", false);
    }
    
    /**
     * 获取登录用户签章列表
     */
    @GetMapping("/signs")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取登录用户签章列表", notes = "获取登录用户签章列表")
    public Resource getLoginUserSigns() throws Exception {
		WebUser webUser = getUser();
		JSONArray r = null;
		if (webUser != null) {
			String signs = webUser.getSigns();

			if (!StringUtil.isBlank(signs)) {
				r = (JsonTmpUtil.fromObject(signs));
			}
		}

		return success("ok", r);
	}

	/**
	 * 根据id获取登录用户签章
	 */
	@GetMapping("/signs/{id}")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "根据id获取登录用户签章", notes = "根据id获取登录用户签章")
	public Resource getLoginUserSign(@PathVariable String id, @RequestParam String password) throws Exception{
		IUser user = getUser();

		JSONArray signs = StringUtil.isBlank(user.getSigns())? new JSONArray() : cn.myapps.util.json.JsonTmpUtil.fromObject(user.getSigns());
		if(signs.isEmpty()) return error(40001, "您还没有设置印章，请使用“印章管理”功能上传并设置印章！", null);
		JSONObject data = null;
		for (int i = 0; i < signs.size(); ++i) {
			JSONObject sign = signs.getJSONObject(i);
			if(sign.getString("id").equals(id)){
				if(password.equals(Security.decryptPassword(sign.getString("password")))){
					data = sign;
					break;
				}else{
					return error(40001, "操作失败，印章密码错误！", null);
				}
			}
		}
		if(data == null){
			return error(40001, "操作失败，印章不存在！", null);
		}
		return success("ok", data);
	}

    /**
     * 新建签章
     */
    @PostMapping("/signs")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "新建签章", notes = "新建签章")
    @ApiImplicitParams({
		@ApiImplicitParam(name = "jsonStr",value = "请求包体",required = true,paramType = "body",dataType = "string")
	})
    public Resource saveLoginUserSign(@RequestBody String jsonStr) throws Exception{
		JSONObject jsonObject = JSONObject.fromObject(jsonStr);
		IUser webUser = getUser();
        String signs = webUser.getSigns();
        JSONArray result = new JSONArray();
        if (!StringUtil.isBlank(signs)) {
        	result = cn.myapps.util.json.JsonTmpUtil.fromObject(signs);
		}
		String password = (String) jsonObject.get("password");
		password = Security.encryptPassword(password);
		jsonObject.put("password", password);

		result.add(jsonObject);
        
        UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
        UserVO user = (UserVO) userProcess.doView(webUser.getId());
        user.setSigns(result.toString());
        userProcess.doUpdate(user);
        return success("ok", "新建成功");
    }
    
    /**
     * 删除签章
     */
    @DeleteMapping("/signs/{id}")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "删除登录用户签章", notes = "删除登录用户签章")
    @ApiImplicitParams({
		@ApiImplicitParam(name = "id",value = "签章id",required = true,paramType = "path",dataType = "string")
	})
    public Resource deleteLoginUserSign(@PathVariable String id) throws Exception{
    	IUser webUser = getUser();
        String signs = webUser.getSigns();
        JSONArray jsonArray = new JSONArray();
        JSONArray result = new JSONArray();
        if (!StringUtil.isBlank(signs)) {
        	jsonArray = cn.myapps.util.json.JsonTmpUtil.fromObject(signs);
		}
        result.addAll(jsonArray);
        for (Object object : jsonArray) {
        	net.sf.json.JSONObject jsonObj = (net.sf.json.JSONObject) object;
        	if (id.equals(jsonObj.get("id"))) {
        		result.remove(jsonObj);
			}
		}
        
        UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
        UserVO user = (UserVO) userProcess.doView(webUser.getId());
        user.setSigns(result.toString());
        userProcess.doUpdate(user);
        return success("ok", "删除成功");
    }
    
    /**
     * 批量删除签章
     */
    @DeleteMapping("/signs")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "批量删除登录用户签章", notes = "批量删除登录用户签章")
    @ApiImplicitParams({
		@ApiImplicitParam(name = "jsonStr",value = "请求包体",required = true,paramType = "body",dataType = "string")
	})
    public Resource deleteLoginUserSigns(@RequestBody String jsonStr) throws Exception{
    	JSONArray newSignsArr = cn.myapps.util.json.JsonTmpUtil.fromObject(jsonStr);
    	
    	IUser webUser = getUser();
        String signs = webUser.getSigns();
        JSONArray oldSignsArr = new JSONArray();
        if (!StringUtil.isBlank(signs)) {
        	oldSignsArr = cn.myapps.util.json.JsonTmpUtil.fromObject(signs);
		}
        
        JSONArray result = new JSONArray();
        result.addAll(oldSignsArr);
        for (Object object : newSignsArr) {
        	String id = (String) object;
        	for (Object oldObject : oldSignsArr) {
        		net.sf.json.JSONObject jsonObj = (net.sf.json.JSONObject) oldObject;
        		if (id.equals(jsonObj.get("id"))) {
        			result.remove(oldObject);
				}
			}
		}
        
        UserProcess userProcess = AuthTimeServiceManager.userRuntimeService();
        UserVO user = (UserVO) userProcess.doView(webUser.getId());
        user.setSigns(result.toString());
        userProcess.doUpdate(user);
        return success("ok", "删除成功");
    }
    
	/**
     * 获取常用意见配置
     */
    @GetMapping("/{userId}/commonOpinions")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取常用意见配置", notes = "获取常用意见配置")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId",value = "用户id",required = true,paramType = "path",dataType = "string")
	})
	public Resource getCommonOpinions(@PathVariable String userId) throws Exception{
		JSONArray opinionJson = new JSONArray();
		UserVO userSetup ;
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		userSetup = (UserVO) process.doView(userId);
		String commonOpinion = null;
		if(userSetup==null) {
			throw new SaasNofoundException(String.format("指定的用户(%s)无效", userId));
		}
		
		if (StringUtil.isBlank(userSetup.getCommonOpinion())
				|| userSetup.getCommonOpinion().equals("[]")) {
			//初始化
			JSONObject opinion = new JSONObject();
			opinion.put("id", Sequence.getUUID());
			opinion.put("content", "同意");
			opinionJson.add(opinion);
			opinion.put("id", Sequence.getUUID());
			opinion.put("content", "批准");
			opinionJson.add(opinion);
			opinion.put("id", Sequence.getUUID());
			opinion.put("content", "OK");
			opinionJson.add(opinion);

			userSetup.setCommonOpinion(opinionJson.toString());
			process.doUpdate(userSetup);
			
		}
		commonOpinion = userSetup.getCommonOpinion();
		opinionJson = cn.myapps.util.json.JsonTmpUtil.fromObject(commonOpinion);

		return success("ok", opinionJson);
	}
	
	/**
     * 添加常用意见
     */
    @PostMapping("/{userId}/commonOpinions")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "添加常用意见", notes = "添加常用意见")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId",value = "用户id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "opinion",value = "意见",required = false,paramType = "query",dataType = "string")
	})
	public Resource addCommonOpinion(@PathVariable String userId, @RequestParam(required=false) String opinion) throws Exception{
		UserVO userSetup = null;
		JSONArray opinionArray = new JSONArray();
		JSONObject opinionJson = new JSONObject();
		opinionJson.put("id", Sequence.getUUID());
		opinionJson.put("content", opinion);
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		userSetup = (UserVO) process.doView(userId);
		if(!StringUtil.isBlank(opinion)){
			if (userSetup != null) {
				String commonOpinion = userSetup.getCommonOpinion();
				if(!StringUtil.isBlank(commonOpinion)){
					opinionArray = cn.myapps.util.json.JsonTmpUtil.fromObject(commonOpinion);
				}
				opinionArray.add(opinionJson);
				userSetup.setCommonOpinion(opinionArray.toString());
				process.doUpdate(userSetup);
			} else {
				opinionArray.add(opinionJson);
				userSetup = new UserVO();
				userSetup.setCommonOpinion(opinionArray.toString());
				userSetup.setId(userId);
				process.doCreate(userSetup);
			}
		}

		return success("ok", opinionJson);
	}
	
	/**
     * 删除常用意见
     */
    @DeleteMapping("/{userId}/commonOpinions/{opId}")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "删除常用意见", notes = "删除常用意见")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId",value = "用户id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "opId",value = "意见",required = false,paramType = "path",dataType = "string")
	})
	public Resource deleteCommonOpinion(@PathVariable String userId, @PathVariable String opId) throws Exception{
		UserVO userSetup = null;
		JSONArray opinionArray = null;
		net.sf.json.JSONObject opinionJson = null;
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		userSetup = (UserVO) process.doView(userId);
		if(userSetup != null && !StringUtil.isBlank(opId)){
			opinionArray = cn.myapps.util.json.JsonTmpUtil.fromObject(userSetup.getCommonOpinion());
			for(int i = 0; i < opinionArray.size(); ++i){
				opinionJson = opinionArray.getJSONObject(i);
				if(opId.equals(opinionJson.getString("id"))){
					opinionArray.remove(i);
					break;
				}
			}
			userSetup.setCommonOpinion(opinionArray.toString());
			process.doUpdate(userSetup);
		}

		return success("ok", opinionJson);
	}
    
	/**
     * 修改常用意见
     */
    @PutMapping("/{userId}/commonOpinions/{opId}")
    @ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "修改常用意见", notes = "修改常用意见")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId",value = "用户id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "opId",value = "意见id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "opinion",value = "意见",required = false,paramType = "path",dataType = "string")
	})
	public Resource updateCommonOpinion(@PathVariable String userId, @PathVariable String opId, @RequestParam(required=false) String opinion) throws Exception{
		UserVO userSetup = null;
		JSONArray opinionArray = null;
		net.sf.json.JSONObject opinionJson = null;
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		userSetup = (UserVO) process.doView(userId);
		if(userSetup != null && !StringUtil.isBlank(opId)){
			try {
				opinionArray = cn.myapps.util.json.JsonTmpUtil.fromObject(userSetup.getCommonOpinion());
				for (int i = 0; i < opinionArray.size(); ++i) {
					opinionJson = opinionArray.getJSONObject(i);
					if (opId.equals(opinionJson.getString("id"))) {
						opinionArray.remove(i);
						opinionJson.clear();
						opinionJson.put("id", opId);
						opinionJson.put("content", opinion);
						opinionArray.add(opinionJson);
						break;
					}
				}
				userSetup.setCommonOpinion(opinionArray.toString());
				process.doUpdate(userSetup);
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return success("ok", opinionJson);
	}

	/**
	 * 根据部门拿用户
	 */
	@GetMapping("/department/{departmentid}/users")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "根据部门拿用户", notes = "根据部门拿用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "departmentid",value = "部门ids",required = true,paramType = "path",dataType = "string")
	})
	public Collection<UserVO> getDepartmentUsers(@PathVariable String departmentid) throws Exception {
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		return process.queryByDepartment(departmentid);
	}

	/**
	 * 根据企业域拿用户
	 */
	@GetMapping("/domain/{domainid}/users")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "根据企业域拿用户", notes = "根据企业域拿用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "domainid",value = "企业域id",required = true,paramType = "path",dataType = "string")
	})
	public Collection<UserVO> getDomaintUsers(@PathVariable String domainid) throws Exception {
		UserProcess process = AuthTimeServiceManager.userRuntimeService();
		return process.queryByDomain(domainid);
	}
}
