package com.xunhong.erp.turbo.user.infrastructure.gateway;

import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.cola.exception.BizException;
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.xunhong.erp.turbo.api.user.dto.cmd.EmployeeRestPasswordCmd;
import com.xunhong.erp.turbo.api.user.dto.cmd.OpenSafeCmd;
import com.xunhong.erp.turbo.api.user.dto.cmd.UpdatePasswordCmd;
import com.xunhong.erp.turbo.api.user.dto.cmd.UserAuthCreateCmd;
import com.xunhong.erp.turbo.api.user.dto.enums.SocialTypeEnum;
import com.xunhong.erp.turbo.api.user.dto.enums.UserStateEnum;
import com.xunhong.erp.turbo.api.user.dto.qry.UserAuthShowQry;
import com.xunhong.erp.turbo.user.domain.entity.UserAuth;
import com.xunhong.erp.turbo.user.domain.gateway.UserAuthGateway;
import com.xunhong.erp.turbo.user.infrastructure.convert.UserAuthConvert;
import com.xunhong.erp.turbo.user.infrastructure.entity.UserAuthDO;
import com.xunhong.erp.turbo.user.infrastructure.entity.UserDO;
import com.xunhong.erp.turbo.user.infrastructure.mapper.UserAuthMapper;
import com.xunhong.erp.turbo.user.infrastructure.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class UserAuthGatewayImpl implements UserAuthGateway {
	private final UserMapper userMapper;
	private final UserAuthMapper userAuthMapper;
	private final UserAuthConvert userAuthConvert;

	@Override
	public UserAuth getByAccount(String username, SocialTypeEnum socialTypeEnum) {
		List<UserAuth> byAccountList = getByAccountList(username, socialTypeEnum);
		if (byAccountList.isEmpty()) {
			return null;
		}

		if ((long) byAccountList.size() > 1) {
			throw new BizException("400", "当前账号异常");
		}

		return byAccountList.get(0);
	}

	public List<UserAuth> getByAccountList(String username, SocialTypeEnum socialTypeEnum) {
		LambdaQueryWrapper<UserAuthDO> queryWrapper = Wrappers.lambdaQuery(UserAuthDO.class);
		queryWrapper.eq(UserAuthDO::getUsername, username);
		queryWrapper.eq(UserAuthDO::getSocialType, socialTypeEnum);
		List<UserAuthDO> userAuthDOList = userAuthMapper.selectList(queryWrapper);

		return userAuthDOList.stream().map(userAuthConvert::toUserAuth).toList();
	}

	@Override
	public UserAuth save(UserAuth userAuth) {
		return userAuth;
	}

	@Override
	@Transactional
	public UserAuth register(UserAuthCreateCmd userAuthCreateCmd) {
		UserDO userDO = new UserDO();
		userDO.setIsAdmin(false);
		userDO.setState(UserStateEnum.ENABLE);
		userMapper.insert(userDO);

		UserAuthDO userAuthDO = userAuthConvert.toUserAuthDO(userAuthCreateCmd);
		userAuthDO.setUserId(userDO.getUserId());
		userAuthDO.setState(1);
		userAuthMapper.insert(userAuthDO);

		userAuthDO.setUserDO(userDO);
		return userAuthConvert.toUserAuth(userAuthDO);
	}

	@Override
	public UserAuth show(UserAuthShowQry userAuthShowQry) {
		QueryWrapper<UserAuthDO> queryWrapper = Wrappers.query(UserAuthDO.class);
		queryWrapper.eq("a.user_id", userAuthShowQry.getUserId());
		UserAuthDO userAuthDO = userAuthMapper.selectOne(queryWrapper);

		return userAuthConvert.toUserAuth(userAuthDO);
	}

	@Override
	public void restPassword(EmployeeRestPasswordCmd employeeRestPasswordCmd) {
		QueryWrapper<UserAuthDO> queryWrapper = Wrappers.query(UserAuthDO.class);
		queryWrapper.eq("a.user_id", employeeRestPasswordCmd.getUserId());
		UserAuthDO userAuthDO = userAuthMapper.selectOne(queryWrapper);

		userAuthDO.setPassword(BCrypt.hashpw(employeeRestPasswordCmd.getPassword()));
		userAuthMapper.updateById(userAuthDO);
	}

	@Override
	public void restPassword(UpdatePasswordCmd updatePasswordCmd) {
		QueryWrapper<UserAuthDO> queryWrapper = Wrappers.query(UserAuthDO.class);
		queryWrapper.eq("a.user_id", updatePasswordCmd.getUserId());
		UserAuthDO userAuthDO = userAuthMapper.selectOne(queryWrapper);

		userAuthDO.setPassword(BCrypt.hashpw(updatePasswordCmd.getPassword()));
		userAuthMapper.updateById(userAuthDO);
	}

	@Override
	public void openSafe(OpenSafeCmd openSafeCmd) {
		QueryWrapper<UserAuthDO> queryWrapper = Wrappers.query(UserAuthDO.class);
		queryWrapper.eq("a.user_id", openSafeCmd.getUserId());
		UserAuthDO userAuthDO = userAuthMapper.selectOne(queryWrapper);

		if (!BCrypt.checkpw(openSafeCmd.getPassword(), userAuthDO.getPassword())) {
			throw new BizException("400", "密码错误");
		}
	}
}
