/*
 * Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yifu.cloud.plus.v1.yifu.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserDTO;
import com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserInfo;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysUser;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.*;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysUserService;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.ErrorCodes;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.MsgUtils;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.util.RedisUtil;
import com.yifu.cloud.plus.v1.yifu.common.log.annotation.SysLog;
import com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TSalaryEmployee;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * @author lengleng
 * @date 2019/2/1
 */
@Tag(name = "用户管理模块", description = "用户管理")
@Log4j2
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {

	private final SysUserService userService;

	// 验证码存缓存里
	private final RedisUtil redisUtil;

	/**
	 * 获取当前用户全部信息
	 *
	 * @return 用户信息
	 */
	@Operation(summary = "获取当前用户全部信息", description = "获取当前用户全部信息")
	@GetMapping(value = {"/info"})
	public R<UserInfoVO> info() {
		String username = SecurityUtils.getUser().getUsername();
		SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
		}
		UserInfo userInfo = userService.getUserInfo(user);
		UserInfoVO vo = new UserInfoVO();
		vo.setSysUser(userInfo.getSysUser());
		vo.setRoles(userInfo.getRoles());
		vo.setPermissions(userInfo.getPermissions());
		return R.ok(vo);
	}

	/**
	 * 获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@Inner
	@GetMapping("/info/{username}")
	public R<UserInfo> info(@PathVariable String username) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
		}
		return R.ok(userService.getUserInfo(user));
	}

	@SysLog("登录获取账号信息异常")
	@Inner
	@GetMapping("/getInfoByUsername")
	public UserInfo infoAPI(@RequestParam(required = true, name = "username") String username,
							@RequestParam(required = false, name = "password") String password) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
		if (Common.isNotNull(user)) {
			userService.ldapLogin(username, password, user);
		}
		if (null == user){
			throw  new RuntimeException("未获取到用户："+ username);
		}
		return userService.getUserInfo(user);
	}

	/**
	 * 根据部门id，查询对应的用户 id 集合
	 *
	 * @param deptIds 部门id 集合
	 * @return 用户 id 集合
	 */
	@Inner
	@GetMapping("/ids")
	public R<List<Long>> listUserIdByDeptIds(@RequestParam("deptIds") Set<Long> deptIds) {
		return R.ok(userService.listUserIdByDeptIds(deptIds));
	}

	/**
	 * 通过ID查询用户信息
	 *
	 * @param id ID
	 * @return 用户信息
	 */
	@GetMapping("/{id}")
	public R<UserVO> user1(@PathVariable String id) {
		return R.ok(userService.getUserVoById(id));
	}

	/**
	 * 根据用户名查询用户信息
	 *
	 * @param username 用户名
	 * @return
	 */
	@GetMapping("/details/{username}")
	public R<SysUser> user(@PathVariable String username) {
		SysUser condition = new SysUser();
		condition.setUsername(username);
		return R.ok(userService.getOne(new QueryWrapper<>(condition)));
	}

	/**
	 * 删除用户信息
	 *
	 * @param id ID
	 * @return R
	 */
	@SysLog("删除用户信息")
	@DeleteMapping("/{id:\\d+}")
	@PreAuthorize("@pms.hasPermission('sys_user_del')")
	public R<Boolean> userDel(@PathVariable Long id) {
		SysUser sysUser = userService.getById(id);
		if (null == sysUser) {
			return R.failed(Boolean.FALSE);
		}
		return R.ok(userService.removeUserById(sysUser));
	}

	/**
	 * 添加用户
	 *
	 * @param userDto 用户信息
	 * @return success/false
	 */
	@SysLog("添加用户")
	@PostMapping
	@PreAuthorize("@pms.hasPermission('sys_user_add')")
	public R<Boolean> user(@RequestBody UserDTO userDto) {
		userDto.setType(CommonConstants.ZERO_STRING);
		return R.ok(userService.saveUser(userDto));
	}

	/**
	 * 更新用户信息
	 *
	 * @param userDto 用户信息
	 * @return R
	 */
	@SysLog("更新用户信息")
	@PutMapping
	@PreAuthorize("@pms.hasPermission('sys_user_edit')")
	public R<Boolean> updateUser(@Valid @RequestBody UserDTO userDto) {
		///userDto.setType(CommonConstants.ZERO_STRING); 2023-04-07 fxj 解决变更LDAP 用户的问题
		return R.ok(userService.updateUser(userDto));
	}

	/**
	 * 修改密码
	 *
	 * @param vo 用户信息
	 * @return R
	 */
	@SysLog("修改密码")
	@PostMapping("/updatePassword")
	public R<String> updatePassword(@RequestBody UserPasswordVo vo) {
		return userService.updatePassword(vo);
	}

	/**
	 * 分页查询用户
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 */
	@GetMapping("/page")
	public R<IPage<List<UserVO>>> getUserPage(Page page, UserDTO userDTO) {
		return R.ok(userService.getUserWithRolePage(page, userDTO));
	}

	/**
	 * 修改个人信息
	 *
	 * @param userDto userDto
	 * @return success/false
	 */
	@SysLog("修改个人信息")
	@PutMapping("/edit")
	public R<Boolean> updateUserInfo(@Valid @RequestBody UserDTO userDto) {
		return R.ok(userService.updateUserInfo(userDto));
	}

	/**
	 * @param username 用户名称
	 * @return 上级部门用户列表
	 */
	@GetMapping("/ancestor/{username}")
	public R<List<SysUser>> listAncestorUsers(@PathVariable String username) {
		return R.ok(userService.listAncestorUsersByUsername(username));
	}

	/**
	 * 导出excel 表格
	 *
	 * @param userDTO 查询条件
	 * @return
	 */
	@ResponseExcel
	@GetMapping("/export")
	@PreAuthorize("@pms.hasPermission('sys_user_import_export')")
	public List<UserExcelVO> export(UserDTO userDTO) {
		return userService.listUser(userDTO);
	}

	/**
	 * 导入用户
	 *
	 * @param excelVOList   用户列表
	 * @param bindingResult 错误信息列表
	 * @return R
	 */
	@PostMapping("/import")
	@PreAuthorize("@pms.hasPermission('sys_user_import_export')")
	public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
		return userService.importUser(excelVOList, bindingResult);
	}

	/**
	 * 从ldap中获取用户
	 *
	 * @return R
	 */
	@SysLog("从ldap中获取用户")
	@PostMapping("/updateUser")
	public R updateByLdap() {
		return R.ok(userService.updateByLdap());
	}

	/**
	 * 从ldap中获取用户
	 *
	 * @return R
	 */
	@SysLog("从ldap中获取用户")
	@PostMapping("/inner/updateUser")
	@Inner
	public R innerUpdateByLdap() {
		return R.ok(userService.updateByLdap());
	}

	/**
	 * 从ldap中验证登录用户
	 *
	 * @return R
	 */
	@SysLog("登录验证")
	@PostMapping("/ldapLogin")
	public R<Boolean> loginAuthentication(@RequestParam String userName, @RequestParam String password) throws NoSuchAlgorithmException {
		return userService.loginAuthentication(userName, password);
	}

	/**
	 * 获取对象基本信息
	 *
	 * @param id
	 * @Author fxj
	 * @Date 2022-07-11 16:42
	 **/
	@Inner
	@GetMapping("/getSimpleUser/{id}")
	public SysUser getSimpleUser(@PathVariable Integer id) {
		return userService.getById(id);
	}

	/**
	 * @return
	 * @Author fxj
	 * @Description 获取所有用户极
	 * @Date 18:20 2022/8/16
	 * @Param
	 **/
	@Inner
	@PostMapping(value = {"/inner/getAllUserName"})
	public AllUserNaVo getAllUserDTO() {
		AllUserNaVo naVo = new AllUserNaVo();
		List<SysUser> sysUsers = userService.list(Wrappers.<SysUser>query().lambda());
		if (Common.isNotEmpty(sysUsers)) {
			HashMap<String, String> nameMap = new HashMap<>();
			for (SysUser u : sysUsers) {
				nameMap.put(u.getUserId(), u.getNickname());
			}
			naVo.setUserNames(nameMap);
		}
		return naVo;
	}

	/**
	 * @return
	 * @Author fxj
	 * @Description 获取所有用户-- 指定用户名
	 * @Date 18:20 2022/8/16
	 * @Param
	 **/
	@Inner
	@PostMapping(value = {"/inner/getUserIdsByUserNames"})
	public SysUserListVo getUserIdsByUserNames(@RequestBody String usernames) {
		SysUserListVo naVo = new SysUserListVo();
		if (Common.isEmpty(usernames)) {
			return naVo;
		}
		List<SysUser> sysUsers = userService.list(Wrappers.<SysUser>query().lambda()
				.in(SysUser::getUsername, Common.getList(usernames)));
		if (Common.isNotEmpty(sysUsers)) {
			List<String> userIds = new ArrayList<>();
			for (SysUser u : sysUsers) {
				userIds.add(u.getUserId());
			}
			naVo.setUserIds(userIds);
			naVo.setUserList(sysUsers);
		}
		return naVo;
	}

	/**
	 * @Author hgw
	 * @Description 获取部门下的用户id
	 * @Date 2022-9-14 11:29:59
	 **/
	@Inner
	@PostMapping(value = {"/inner/getUserIdByDeptIds"})
	public String getUserIdByDeptIds(@RequestBody String deptIds) {
		StringBuilder userIds = new StringBuilder("'0'");
		if (Common.isNotNull(deptIds)) {
			List<String> list = Common.initStrToList(deptIds, ",");
			List<SysUser> sysUsers = userService.list(Wrappers.<SysUser>query().lambda().in(SysUser::getDeptId, list));
			if (Common.isNotEmpty(sysUsers)) {
				for (SysUser u : sysUsers) {
					userIds.append(",'").append(u.getUserId()).append("'");
				}
			}
		}
		return userIds.toString();
	}

	/**
	 * @Author hgw
	 * @Description 获取部门下的用户id
	 * @Date 2022-9-14 11:29:59
	 **/
	@Inner
	@PostMapping(value = {"/inner/getUserNamedByDeptIds"})
	public String getUserNameByDeptIds(@RequestBody String deptIds) {
		StringBuilder userIds = new StringBuilder("'0'");
		if (Common.isNotNull(deptIds)) {
			List<String> list = Common.initStrToList(deptIds, ",");
			List<SysUser> sysUsers = userService.list(Wrappers.<SysUser>query().lambda().in(SysUser::getDeptId, list));
			if (Common.isNotEmpty(sysUsers)) {
				for (SysUser u : sysUsers) {
					userIds.append(",'").append(u.getUsername()).append("'");
				}
			}
		}
		return userIds.toString();
	}

	@Inner
	@PostMapping(value = {"/inner/getSimpleUser"})
	public SysUser getSimpleUser(@RequestBody String userId) {
		return userService.getById(userId);
	}

	/**
	 * @param nickName 用户名称
	 * @return 上级部门用户列表
	 */
	@GetMapping("/getSysUserList")
	@Operation(summary = "获取所有系统人员", description = "获取所有系统人员")
	public R<List<SysUser>> getSysUserList(@RequestParam(required = false) String nickName) {
		List<SysUser> sysUserList;
		if (Common.isNotNull(nickName)) {
			sysUserList = userService.list(Wrappers.<SysUser>query().lambda().like(SysUser::getNickname, nickName));
		} else {
			sysUserList = userService.list();
		}
		return R.ok(sysUserList);
	}

	/**
	 * @Description: 获取C端用户是否存在
	 * @Author: hgw
	 * @Date: 2022/12/13 14:50
	 * @return: java.lang.Integer
	 **/
	@Inner
	@PostMapping("/inner/getCountByIdCard")
	public Integer getCountByIdCard(@RequestBody SysUser user) {
		return (int) userService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, user.getUsername())
				.eq(SysUser::getDelFlag, CommonConstants.ZERO_STRING)
				.isNotNull(SysUser::getWxOpenid));
	}

	/**
	 * C端用户信息注册
	 *
	 * @return
	 */
	@Operation(description = "c端用户信息注册")
	@PostMapping("/employee/registration")
	public R<String> registration(@RequestBody TSalaryEmployee employeeInfo, String openId, String headImgUrl, String cCode) {
		if (null == employeeInfo || Common.isEmpty(employeeInfo.getEmpIdcard()) || Common.isEmpty(employeeInfo.getEmpPhone())) {
			return R.failed("身份证和手机号不能为空");
		}
		if (Common.isEmpty(openId)) {
			return R.failed("openId不能为空！");
		}
		if (null != redisUtil.get(CommonConstants.C_PREFIX.concat(employeeInfo.getEmpPhone()))) {
			String code = (String) redisUtil.get(CommonConstants.C_PREFIX.concat(employeeInfo.getEmpPhone()));
			if (!code.equals(cCode)) {
				return R.failed("验证码错误，请核实");
			}
		} else {
			return R.failed("未找到手机号对应的验证码或验证码已超时，请重新获取");
		}
		userService.saveCUser(employeeInfo.getEmpIdcard(), employeeInfo.getEmpName(), employeeInfo.getEmpPhone(), openId, headImgUrl);
		return R.ok();
	}

	/**
	 * 根据openid和类型获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@Inner
	@PostMapping("/inner/getSysUserByWxOpenId")
	public UserInfo getSysUserByWxOpenId(@RequestBody SysUser users) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getWxOpenid, users.getWxOpenid()).last(CommonConstants.LAST_ONE_SQL));
		if (user == null) {
			return null;
		}
		UserInfo info = userService.getUserInfo(user);
		return info;
	}
}
