package com.cyksj.web.controller.manage.cms;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.annotation.Log;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Codec;
import com.cyksj.dto.Result;
import com.cyksj.enums.BusinessType;
import com.cyksj.enums.GatewayApiCode;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.PhoneCodeMapper;
import com.cyksj.mapper.manage.cms.CmsUserMapper;
import com.cyksj.model.entity.CmsUser;
import com.cyksj.model.entity.PhoneCode;
import com.cyksj.model.manage.dto.AdminInfo;
import com.cyksj.model.request.CmsUserReq;
import com.cyksj.model.views.CmsUserVO;
import com.cyksj.service.mange.CmsAccountService;
import com.cyksj.service.mange.business.UserBusinessRateService;
import com.cyksj.service.mange.cms.CmsUserManager;
import com.cyksj.service.mange.cms.manager.service.CacheService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/*
 *项目名: netflix
 *文件名: CmsAdminUserController
 *创建者: JavaZou
 *创建时间:2023/1/11 14:26
 */
@RestController
@RequestMapping("/manage/user")
@RequiredArgsConstructor
@Slf4j
public class CmsAdminUserController {
	private final CmsUserMapper cmsUserMapper;

	private final PhoneCodeMapper phoneCodeMapper;

	private final CmsUserManager cmsUserManager;

	private final CacheService cacheService;

	private final BeanSearcher beanSearcher;

	private final CmsAccountService cmsAccountService;

	private final HttpServletRequest request;

	private final UserBusinessRateService userBusinessRateService;

	@PostMapping(value = "/login")
	public Result<String> login(@RequestBody CmsUser adminRequest) throws Exception {
		CmsUser admin = cmsUserMapper.selectOne(
				new QueryWrapper<CmsUser>().lambda().eq(CmsUser::getPhone,adminRequest.getPhone()).last("limit 1"));

		if (null == admin) {
			throw BusinessRuntimeException.getInstance("该用户不存在.");
		}
		if (null == admin.getStatus() || !admin.getStatus()) {
			throw BusinessRuntimeException.getInstance("无登录权限.");
		}

		// 对比密码
		String encodePasscode = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(adminRequest.getPassword()).toBase64String();

		if (!StringUtils.equals(admin.getPassword(), encodePasscode)) {
			throw BusinessRuntimeException.getInstance("密码有误.");
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	@PostMapping("/post")
	@Log(module = "用户管理/新增用户", businessType = BusinessType.POST, isSaveRequestData = true)
	@Transactional(rollbackFor = Throwable.class)
	public Result<String> saveAdmin(@RequestBody @Validated CmsUserReq cmsUserReq) throws Exception {
		Long adminId = StpUtil.getLoginIdAsLong();
		CmsUser exist = cmsUserMapper.selectById(adminId);
		if (exist == null) {
			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
		}
		CmsUser cmsUser = new CmsUser();
		BeanUtil.copyProperties(cmsUserReq, cmsUser);
		if (StringUtils.isNotBlank(cmsUserReq.getPassword())) {
			cmsUser.setPassword(Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(cmsUserReq.getPassword()).toBase64String());
		}
		if (cmsUser.getId() == null) {
			CmsUser ad = cmsUserMapper.selectOne(new LambdaQueryWrapper<CmsUser>().eq(CmsUser::getPhone, cmsUser.getPhone()).last("limit 1"));
			if (ad != null) {
				throw BusinessRuntimeException.getInstance("该账号已存在.");
			}
		}
		boolean mobile = Validator.isMobile(cmsUser.getPhone());
		if (!mobile) {
			throw BusinessRuntimeException.getInstance("请输入正确的手机号");
		}

		try {
			cmsUserMapper.insert(cmsUser);
			//保存用户角色关系
			cmsUserManager.saveUserRoleRelation(cmsUser.getId(), cmsUserReq.getRoleIds());
		} catch (DuplicateKeyException e) {
			throw BusinessRuntimeException.getInstance("手机号重复");
		}

		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 删除管理员
	 */
	@DeleteMapping("/delete/{id}")
	@Log(module = "用户管理/删除用户", businessType = BusinessType.DELETE)
	public Result<String> deleteAdminById(@PathVariable Long id) throws Exception {
		Long adminId = StpUtil.getLoginIdAsLong();
		CmsUser exist = cmsUserMapper.selectById(adminId);
		if (exist == null) {
			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
		}
		//是不是客服
		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
				.field(CmsUserVO::getId, id)
				.build());
		if (isCustomer == null) {
			throw BusinessRuntimeException.getInstance("被删除的用户不存在");
		}

		if (id.equals(adminId)) {
			throw BusinessRuntimeException.getInstance("无法删除自己");
		}
		//是商务直接删除比例
		userBusinessRateService.deleteBusinessRateByUid(adminId);

		if (isCustomer.getRoleNames().contains("客服")) {
			//是否未修改密码的账号
			cmsAccountService.assignDeleteCustomerAccount(id);
		}

		//删除用户角色关联关系、缓存
		cmsUserManager.delUserRoleRelation(id);
		cmsUserMapper.deleteById(id);
		//删除用户,将上线的用户踢下
		StpUtil.logoutByLoginId(id);
		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
	}

	/**
	 * 编辑管理员
	 */
	@PutMapping("/put")
	@Log(module = "用户管理/编辑用户", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> editAdmin(@RequestBody CmsUserReq cmsUserReq) throws Exception {
		Long adminId = StpUtil.getLoginIdAsLong();
		CmsUser exist = cmsUserMapper.selectById(adminId);
		if (exist == null) {
			throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
		}
		CmsUser user = cmsUserMapper.selectById(cmsUserReq.getId());
		if (cmsUserReq.getId() == null || user == null) {
			throw BusinessRuntimeException.getInstance("账号不存在");
		}
		Boolean flag = false;
		if (StrUtil.isNotEmpty(cmsUserReq.getPhone())) {
			boolean mobile = Validator.isMobile(cmsUserReq.getPhone());
			if (!mobile) {
				throw BusinessRuntimeException.getInstance("请输入正确的手机号");
			}
			if (!cmsUserReq.getPhone().equals(user.getPhone())) {
				flag = true;
			}
		}
		if (StrUtil.isNotEmpty(cmsUserReq.getPassword())) {
			String encodePwd = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(cmsUserReq.getPassword()).toBase64String();
			cmsUserReq.setPassword(encodePwd);
			if (!encodePwd.equals(user.getPassword())) {
				flag = true;
				user.setPassword(encodePwd);
			}
		}
		user.setNickname(cmsUserReq.getNickname());
		if (StrUtil.isNotBlank(cmsUserReq.getRoleIds())) {
			cmsUserManager.delUserRoleRelation(user.getId());
			cmsUserManager.saveUserRoleRelationAndCache(user, cmsUserReq.getRoleIds());
		}
		user.setPhone(cmsUserReq.getPhone());
		user.setModifiedBy(exist.getNickname());
		cmsUserMapper.updateById(user);
		if (flag) {
			StpUtil.logoutByLoginId(cmsUserReq.getId());
		}
		//是不是客服
		CmsUserVO isCustomer = beanSearcher.searchFirst(CmsUserVO.class, MapUtils.builder()
				.field(CmsUserVO::getId, cmsUserReq.getId())
				.build());
		if (isCustomer != null && !isCustomer.getRoleNames().contains("客服")) {
			//是否未修改密码的账号
			cmsAccountService.assignDeleteCustomerAccount(cmsUserReq.getId());
		}

		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
	}

	@PutMapping("/put/status/{id}")
	public Result<String> updateUserStatus(@PathVariable("id") Integer id) {
		if (id == null || id < 1) {
			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_USER_NO_FIND);
		}
		CmsUser cmsUser = cmsUserMapper.selectById(id);
		if (cmsUser == null) {
			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_USER_NO_FIND);
		}
		cmsUser.setStatus(!cmsUser.getStatus());
		cmsUserMapper.updateById(cmsUser);
		if (!cmsUser.getStatus()) {
			//状态为禁用时,将上线的用户下线
			StpUtil.logoutByLoginId(cmsUser.getId());
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("用户状态变更成功");
	}

	@SneakyThrows
	@PutMapping("/put/reset/pwd/{id}")
	public Result<String> resetPwd(@PathVariable("id") Integer id) {
		CmsUser cmsUser = cmsUserMapper.selectById(id);
		cmsUser.setPassword(Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(Constant.INITIAL_PASSWORD).toBase64String());
		cmsUserMapper.updateById(cmsUser);
		cacheService.saveUser(cmsUser.getId());
		return GatewayResponse.SUCCESS.newBuilder().toResult("重置密码成功");
	}

	/**
	 * 手机号获取登录信息
	 */
	@GetMapping("/get/loginInfo")
	public Result<AdminInfo> getLoginInfo(String phone, String code) throws Exception {
		CmsUser admin = cmsUserMapper.selectOne(
				new QueryWrapper<CmsUser>().lambda().eq(CmsUser::getPhone, phone).last("limit 1"));
		if (null == admin) {
			throw BusinessRuntimeException.getInstance("该用户不存在.");
		}
		if (StrUtil.hasEmpty(phone, code)) {
			throw BusinessRuntimeException.getInstance("请输入对应信息");
		}
		DateTime now = DateTime.now();
		PhoneCode phoneCode = phoneCodeMapper.selectOne(Wrappers.lambdaQuery(PhoneCode.class).eq(PhoneCode::getPhone, phone).last("limit 1"));
		if (phoneCode == null || StrUtil.isEmpty(phoneCode.getCode())) {
			throw BusinessRuntimeException.getInstance("请重新获取手机验证码");
		}
		//3分钟失效
		Date updateTime = phoneCode.getUpdateTime();
		DateTime afterFiveMinutes = DateUtil.offsetMinute(updateTime, 3);
		if (now.isAfter(afterFiveMinutes)) {
			throw BusinessRuntimeException.getInstance("手机验证码已失效,请重新获取");
		}
		if (!StrUtil.equals(code, phoneCode.getCode())) {
			throw BusinessRuntimeException.getInstance("手机验证码错误,请重新输入");
		}
		// 生成token

		StpUtil.login(admin.getId());

		String token = StpUtil.getTokenValue();

		admin.setPassword("");

		AdminInfo info = new AdminInfo();
		info.setInfo2(admin);
		info.setToken(token);

		//缓存用户信息
		cmsUserManager.loadUserRedisCache(admin);

		//用户权限
		info.setPermissions(cmsUserManager.getUserPermissions(admin.getId()));

		//用户角色
		info.setRoles(cmsUserManager.getUserRoles(admin.getId()));
		return GatewayResponse.SUCCESS.newBuilder().toResult(info);
	}

	@GetMapping("/get/list")
	public Result<SearchResult<CmsUserVO>> list(String roleNames) {
		long userId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (StrUtil.isNotEmpty(roleNames) && roleNames.contains("客服")) {
			CmsUser user = cmsUserManager.getUser(userId);
			if (user != null && user.getRoleNames() != null && user.getRoleNames().contains("客服")) {
				builder.field(CmsUserVO::getId, userId);
			}
		}
		SearchResult<CmsUserVO> search = beanSearcher.search(CmsUserVO.class, builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}
}
