package com.qunzhixinxi.hnqz.admin.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
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.qunzhixinxi.hnqz.admin.api.entity.SysDictItem;
import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackage;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackageStatus;
import com.qunzhixinxi.hnqz.admin.entity.WmTeam;
import com.qunzhixinxi.hnqz.admin.entity.base.BaseEntity;
import com.qunzhixinxi.hnqz.admin.entity.model.excel.WmTeamExcelModel;
import com.qunzhixinxi.hnqz.admin.enums.DelEnum;
import com.qunzhixinxi.hnqz.admin.enums.EnableEnum;
import com.qunzhixinxi.hnqz.admin.enums.PackageStatusEnum;
import com.qunzhixinxi.hnqz.admin.enums.ScorePackageStatusEnum;
import com.qunzhixinxi.hnqz.admin.mapper.SysUserMapper;
import com.qunzhixinxi.hnqz.admin.service.SysDictItemService;
import com.qunzhixinxi.hnqz.admin.service.WmScorePackageService;
import com.qunzhixinxi.hnqz.admin.service.WmScorePackageStatusService;
import com.qunzhixinxi.hnqz.admin.service.WmTeamService;
import com.qunzhixinxi.hnqz.common.core.util.R;
import com.qunzhixinxi.hnqz.common.log.annotation.SysLog;
import com.qunzhixinxi.hnqz.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.annotation.Validated;
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.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 团队管理控制层
 *
 * @author lixuesong
 * @date 2021年12月08日 13:57
 */
@Slf4j
@RestController
@RequestMapping("/team")
@AllArgsConstructor
public class WmTeamController {

	private final WmTeamService wmTeamService;

	private final WmScorePackageService wmScorePackageService;

	private final WmScorePackageStatusService wmScorePackageStatusService;

	private final SysUserMapper sysUserMapper;

	private final SysDictItemService sysDictItemService;

	/**
	 * 保存
	 *
	 * @param wmTeam
	 * @return
	 */
	@SysLog("保存团队")
	@PostMapping
	public R<?> save(@RequestBody @Validated({BaseEntity.Create.class}) WmTeam wmTeam) {
		if (StrUtil.containsBlank(wmTeam.getName())) {
			return R.failed("团队名称不能包含空格");
		}
		int count = wmTeamService.count(Wrappers.<WmTeam>lambdaQuery()
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val())
				.eq(WmTeam::getName, wmTeam.getName()));
		if (count > 0) {
			return R.failed("团队名称已存在");
		}
		wmTeam.setDeptId(SecurityUtils.getUser().getDeptId());
		wmTeam.setCreateTime(LocalDateTime.now());
		wmTeam.setCreateUser(SecurityUtils.getUser().getId());
		if (wmTeam.getLeader() != null) {
			wmTeam.setEnableFlag(EnableEnum.ENABLE.val());
		}
		wmTeam.setDelFlag(DelEnum.NOT_DEL.val());
		wmTeamService.save(wmTeam);
		return R.ok();
	}

	/**
	 * 保存
	 *
	 * @param wmTeam
	 * @return
	 */
	@SysLog("保存团队-平台")
	@PostMapping("/save-by-dept")
	public R<?> saveByDept(@RequestBody @Validated({BaseEntity.Create.class}) WmTeam wmTeam) {
		if (wmTeam.getDeptId() == null) {
			return R.failed("deptId不能为空");
		}
		if (StrUtil.containsBlank(wmTeam.getName())) {
			return R.failed("团队名称不能包含空格");
		}
		int count = wmTeamService.count(Wrappers.<WmTeam>lambdaQuery()
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val())
				.eq(WmTeam::getName, wmTeam.getName()));
		if (count > 0) {
			return R.failed("团队名称已存在");
		}
		wmTeam.setDeptId(wmTeam.getDeptId());
		wmTeam.setCreateTime(LocalDateTime.now());
		wmTeam.setCreateUser(SecurityUtils.getUser().getId());
		if (wmTeam.getLeader() != null) {
			wmTeam.setEnableFlag(EnableEnum.ENABLE.val());
		}
		wmTeam.setDelFlag(DelEnum.NOT_DEL.val());
		wmTeamService.save(wmTeam);
		return R.ok();
	}

	/**
	 * 更新
	 *
	 * @param wmTeam
	 * @return
	 */
	@SysLog("更新团队")
	@PutMapping
	public R<?> update(@RequestBody @Validated({BaseEntity.Update.class}) WmTeam wmTeam) {
		if (StrUtil.isNotBlank(wmTeam.getName()) && StrUtil.containsBlank(wmTeam.getName())) {
			return R.failed("团队名称不能包含空格");
		}
		int count = wmTeamService.count(Wrappers.<WmTeam>lambdaQuery()
				.ne(WmTeam::getId, wmTeam.getId())
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val())
				.eq(WmTeam::getName, wmTeam.getName()));
		if (count > 0) {
			return R.failed("团队名称已存在");
		}
		// 校验被移除的人员是否正在做任务
		WmTeam queryTeam = wmTeamService.getById(wmTeam.getId());
		if (ArrayUtil.isNotEmpty(queryTeam.getMember())) {
			// 计算单差集，找到被删除的成员
			List<String> deletedMemberList =
					CollectionUtil.subtractToList(CollectionUtil.toList(queryTeam.getMember()), CollectionUtil.toList(wmTeam.getMember()));
			if (CollectionUtil.isNotEmpty(deletedMemberList)) {
				// 查询被删除的人员正在做的任务
				List<WmScorePackage> scorePackageList = wmScorePackageService.list(Wrappers.<WmScorePackage>lambdaQuery()
						.le(WmScorePackage::getScorePackageStatus, ScorePackageStatusEnum.IN_PROGRESS.val())
						.eq(WmScorePackage::getPackageUserScope, wmTeam.getId())
						.eq(WmScorePackage::getDeptId, wmTeam.getDeptId())
						.eq(WmScorePackage::getDelFlag, DelEnum.NOT_DEL.val())
						.eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val()));
				if (CollectionUtil.isNotEmpty(scorePackageList)) {
					List<String> packageIdList = scorePackageList.stream().map(WmScorePackage::getId).collect(Collectors.toList());
					List<WmScorePackageStatus> packageStatusList = wmScorePackageStatusService.list(Wrappers.<WmScorePackageStatus>lambdaQuery()
							.in(WmScorePackageStatus::getPackageId, packageIdList)
							.in(WmScorePackageStatus::getUserId, deletedMemberList)
							.eq(WmScorePackageStatus::getStatus, PackageStatusEnum.APPROVED.val())
							.eq(WmScorePackageStatus::getDelFlag, DelEnum.NOT_DEL.val())
							.eq(WmScorePackageStatus::getEnableFlag, EnableEnum.ENABLE.val()));
					if (CollectionUtil.isNotEmpty(packageStatusList)) {
						Set<String> statusUserSet = packageStatusList.stream().map(WmScorePackageStatus::getUserId).collect(Collectors.toSet());
						List<SysUser> sysUsers = sysUserMapper.selectBatchIds(statusUserSet);
						List<String> userNameList = sysUsers.stream().map(SysUser::getRealname).collect(Collectors.toList());
						return R.failed(String.format("正在团队中做任务的人员'%s'，不能从团队中移除", String.join(",", userNameList)));
					}
				}
			}
		}

		if (wmTeam.getLeader() != null) {
			wmTeam.setEnableFlag(EnableEnum.ENABLE.val());
		}
		wmTeam.setUpdateTime(LocalDateTime.now());
		wmTeam.setUpdateUser(SecurityUtils.getUser().getId());
		wmTeamService.updateById(wmTeam);
		return R.ok();
	}

	/**
	 * 解散团队
	 *
	 * @param id
	 * @return
	 */
	@SysLog("解散团队")
	@PostMapping("/{id}/dissolve")
	public R<?> dissolve(@PathVariable("id") Integer id) {
		// 查询团队是否还有任务在进行
		int packageCount = wmScorePackageService.count(Wrappers.<WmScorePackage>lambdaQuery()
				.eq(WmScorePackage::getDelFlag, DelEnum.NOT_DEL.val())
				.eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val())
				.eq(WmScorePackage::getPackageUserScope, id)
				.le(WmScorePackage::getScorePackageStatus, ScorePackageStatusEnum.IN_PROGRESS.val()));
		if (packageCount > 0) {
			return R.failed("该团队还有任务在进行，不能解散");
		}
		// 设置为禁用
		wmTeamService.update(Wrappers.<WmTeam>lambdaUpdate()
				.eq(WmTeam::getId, id)
				.set(WmTeam::getDelFlag, DelEnum.DELETED.val())
				.set(WmTeam::getUpdateTime, LocalDateTime.now())
				.set(WmTeam::getUpdateUser, SecurityUtils.getUser().getId()));
		return R.ok();
	}

	/**
	 * 批量导入
	 *
	 * @param teamExcelModelList
	 * @return
	 */
	@SysLog("团队成员批量导入")
	@PostMapping("/batch-import")
	public R<?> batchImport(@RequestExcel(ignoreEmptyRow = true) List<WmTeamExcelModel> teamExcelModelList, @RequestParam("teamId") String teamId) {
		// 参数校验
		if (CollectionUtils.isEmpty(teamExcelModelList)) {
			log.error("空报表，不能上传");
			return R.failed("空报表，不能上传");
		}

		Map<String, List<WmTeamExcelModel>> excelMap = teamExcelModelList.stream()
				.filter(wmTeamExcelModel ->
						!StrUtil.isAllBlank(wmTeamExcelModel.getId(), wmTeamExcelModel.getUsername(), wmTeamExcelModel.getRealname()))
				.map(wmTeamExcelModel -> {
					wmTeamExcelModel.setId(StrUtil.trim(wmTeamExcelModel.getId()));
					wmTeamExcelModel.setRealname(StrUtil.trim(wmTeamExcelModel.getRealname()));
					wmTeamExcelModel.setUsername(StrUtil.trim(wmTeamExcelModel.getUsername()));
					return wmTeamExcelModel;
				})
				.collect(Collectors.groupingBy(WmTeamExcelModel::getUsername));

		// 实际的处理业务
		Map<String, String> errorMap = wmTeamService.batchImport(Integer.valueOf(teamId), excelMap);

		// 返回上传结果
		Map<String, Object> result = new HashMap<>(3);
		if (CollectionUtil.isEmpty(errorMap)) {
			result.put("code", "SUCCESS");
			result.put("message", "上传成功");
			result.put("data", null);
			return R.ok(result);
		} else {
			log.error("上传数据错误，{}", JSONUtil.toJsonStr(errorMap));
			result.put("code", "FAILURE");
			result.put("message", "上传数据错误");
			result.put("data", errorMap);
			return R.failed(result);

		}
	}

	/**
	 * 查询团队列表
	 *
	 * @param page
	 * @return
	 */
	@GetMapping("/list")
	public R<IPage<WmTeam>> list(Page<WmTeam> page) {
		Page<WmTeam> teamManagePage = wmTeamService.page(page, Wrappers.<WmTeam>lambdaQuery()
				.eq(WmTeam::getDeptId, SecurityUtils.getUser().getDeptId())
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val()));
		teamManagePage.getRecords().forEach(wmTeamManage -> {
			if (ArrayUtil.isNotEmpty(wmTeamManage.getLeader())) {
				List<SysUser> leaderList = sysUserMapper.selectBatchIds(CollectionUtil.toList(wmTeamManage.getLeader()));
				wmTeamManage.setLeaderName(leaderList.stream().map(SysUser::getRealname).toArray(String[]::new));
			}
			if (ArrayUtil.isNotEmpty(wmTeamManage.getMember())) {
				List<SysUser> userList = sysUserMapper.selectBatchIds(CollectionUtil.toList(wmTeamManage.getMember()));
				wmTeamManage.setMemberName(userList.stream().map(SysUser::getRealname).toArray(String[]::new));
			}
		});
		return R.ok(teamManagePage);
	}

	/**
	 * 根据deptId查询团队列表
	 *
	 * @param page
	 * @param deptId
	 * @return
	 */
	@GetMapping("/list-by-dept")
	public R<IPage<WmTeam>> list(Page<WmTeam> page, @RequestParam(value = "deptId", required = false) Integer deptId) {
		if (deptId == null) {
			return R.ok(page);
		}
		Page<WmTeam> teamManagePage = wmTeamService.page(page, Wrappers.<WmTeam>lambdaQuery()
				.eq(WmTeam::getDeptId, deptId)
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val()));
		teamManagePage.getRecords().forEach(wmTeamManage -> {
			if (ArrayUtil.isNotEmpty(wmTeamManage.getLeader())) {
				List<SysUser> leaderList = sysUserMapper.selectBatchIds(CollectionUtil.toList(wmTeamManage.getLeader()));
				wmTeamManage.setLeaderName(leaderList.stream().map(SysUser::getRealname).toArray(String[]::new));
			}
			if (ArrayUtil.isNotEmpty(wmTeamManage.getMember())) {
				List<SysUser> userList = sysUserMapper.selectBatchIds(CollectionUtil.toList(wmTeamManage.getMember()));
				wmTeamManage.setMemberName(userList.stream().map(SysUser::getRealname).toArray(String[]::new));
			}
		});
		return R.ok(teamManagePage);
	}

	/**
	 * 查询团队可选择人员
	 *
	 * @param deptId          部门id
	 * @param teamId          团队id
	 * @param realNameOrPhone 姓名或手机号
	 * @return
	 */
	@GetMapping("/list-selectable-user")
	public R<Map<String, Object>> listSelectableUser(@RequestParam(value = "deptId", required = false) Integer deptId,
													 @RequestParam(value = "teamId", required = false) Integer teamId,
													 @RequestParam(value = "realNameOrPhone", required = false) String realNameOrPhone) {
		Map<String, Object> map = wmTeamService.listSelectableUser(deptId, teamId, realNameOrPhone);
		return R.ok(map);
	}

	/**
	 * 查询团队可选择人员-搜索
	 *
	 * @param deptId          部门id
	 * @param realNameOrPhone 姓名或手机号
	 * @return
	 */
	@GetMapping("/list-selectable-user-for-search")
	public R<Map<String, Object>> listSelectableUserForSearch(@RequestParam(value = "deptId", required = false) Integer deptId,
													 @RequestParam(value = "realNameOrPhone", required = false) String realNameOrPhone) {
		Map<String, Object> map = wmTeamService.listSelectableUser(deptId, null, realNameOrPhone);
		return R.ok(map);
	}

	/**
	 * 查询接单对象范围
	 *
	 * @return
	 */
	@GetMapping("/list-package-user-scope")
	public R<List<Map<String, Object>>> listPackageUserScope() {
		List<Map<String, Object>> resultList = new ArrayList<>();
		Integer deptId = SecurityUtils.getUser().getDeptId();
		Integer userId = SecurityUtils.getUser().getId();
		// 查询当前企业下的团队
		List<WmTeam> list = wmTeamService.list(Wrappers.<WmTeam>lambdaQuery()
				.eq(WmTeam::getDeptId, deptId)
				.eq(WmTeam::getDelFlag, DelEnum.NOT_DEL.val())
				.eq(WmTeam::getEnableFlag, EnableEnum.ENABLE.val())
				.apply("FIND_IN_SET({0}, leader)", String.valueOf(userId)));
		if (CollectionUtil.isNotEmpty(list)) {
			List<Map<String, Object>> mapList = list.stream().map(wmTeam -> {
				Map<String, Object> teamMap = MapUtil.newHashMap(2);
				teamMap.put("label", wmTeam.getName());
				teamMap.put("value", String.valueOf(wmTeam.getId()));
				return teamMap;
			}).collect(Collectors.toList());
			resultList.addAll(mapList);
		} else {
			// 原有的字典数据项
			List<SysDictItem> packageUserScopeDictList = sysDictItemService.list(Wrappers.<SysDictItem>lambdaQuery()
					.eq(SysDictItem::getType, "package_user_scope")
					.eq(SysDictItem::getDelFlag, DelEnum.NOT_DEL.val()));
			if (CollectionUtil.isNotEmpty(packageUserScopeDictList)) {
				List<Map<String, Object>> dictMapList = packageUserScopeDictList.stream().map(sysDictItem -> {
					Map<String, Object> dictMap = MapUtil.newHashMap(2);
					dictMap.put("label", sysDictItem.getLabel());
					dictMap.put("value", sysDictItem.getValue());
					return dictMap;
				}).collect(Collectors.toList());
				resultList.addAll(dictMapList);
			}
		}

		return R.ok(resultList);
	}
}
