package com.seer.teach.user.admin.api;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seer.teach.common.dto.mq.im.MqUserInfoDTO;
import com.seer.teach.common.enums.im.ImMqTopicEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.enums.RoleEnum;
import com.seer.teach.common.enums.im.UserInfoTopiTagEnum;
import com.seer.teach.common.enums.iot.IsInfoEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.CommonUtils;
import com.seer.teach.iot.api.UserDeviceServiceApi;
import com.seer.teach.pay.api.wallet.CoinAccountServiceApi;
import com.seer.teach.pay.api.wallet.dto.UserCoinAccountRespDTO;
import com.seer.teach.user.api.UserInfoServiceApi;
import com.seer.teach.user.api.dto.*;
import com.seer.teach.user.convert.UserInfoConvert;
import com.seer.teach.user.entity.*;
import com.seer.teach.user.mq.MqProducer;
import com.seer.teach.user.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

@Slf4j
@RequiredArgsConstructor
@RestController
public class UserInfoServiceApiImpl implements UserInfoServiceApi {


    private final IUserService userService;

    private final IUserExtendService userExtendService;

    private final IAuthorityService authorityService;

    private final IUserRelationService userRelationService;

    private final IUserRoleService userRoleService;

    private final IGradeService gradeService;

    private final ILevelService levelService;

    private final MqProducer mqProducer;

    private final UserDeviceServiceApi userDeviceServiceApi;

    private final CoinAccountServiceApi coinAccountServiceApi;

    private final UserInfoServiceApi userInfoServiceApi;

    private final IUserAuthService userAuthService;


    /**
     * 根据用户ID获取用户信息
     *
     * @param id 用户ID
     * @return 用户信息DTO对象
     */
    @Override
    public UserInfoDTO getById(Integer id) {
        log.info("getById:{}", id);
        UserEntity userEntity = userService.getById(id);
        AssertUtils.notNull(userEntity, ResultCodeEnum.USER_NOT_FOUND);
        log.info("userEntity:{}", userEntity);
        UserExtendEntity userExtendEntity = userExtendService.getUserExtendByUserId(id);
        log.info("userExtendEntity:{}", userExtendEntity);
        return UserInfoConvert.INSTANCE.convertOne(userEntity, userExtendEntity);
    }

    @Override
    public List<UserInfoDTO> getListByUserIds(Collection<Integer> ids) {
        List<UserEntity> userList = userService.getListByUserIds(ids);
        return UserInfoConvert.INSTANCE.convertList(userList);
    }

    @Override
    public List<UserInfoDTO> getDefaultChildrenByUserIds(Collection<Integer> ids) {
        List<UserEntity> userList = userService.getDefaultChildrenByUserIds(ids);
        return UserInfoConvert.INSTANCE.convertList(userList);
    }

    @Override
    public UserAuthDTO getUserAuthByUserIdAndAppId(Integer userId, String appId) {
        return UserInfoConvert.INSTANCE.convertUserAuthOne(userAuthService.getOneByUserIdAndAppId(userId, appId));
    }

    @Override
    public List<UserAuthDTO> getUserAuthListByUserIdsAndAppId(UserAuthQueryDTO userAuthQueryDTO) {
        List<UserAuthEntity> userAuthList = userAuthService.getUserAuthListByUserIdsAndAppId(userAuthQueryDTO.getUserIds(), userAuthQueryDTO.getAppId());
        return UserInfoConvert.INSTANCE.convertUserAuthList(userAuthList);
    }

    /**
     * 根据OpenId获取用户信息
     *
     * @param openId 微信OpenId
     * @return 用户信息DTO对象
     */
    @Override
    public UserInfoDTO getByOpenId(String openId) {
        UserAuthEntity userAuthEntity = userAuthService.getOneByOpenId(openId);
        if (Objects.isNull(userAuthEntity)) {
            return null;
        }
        UserEntity userEntity = userService.getById(userAuthEntity.getUserId());
        return UserInfoConvert.INSTANCE.convertOne(userEntity);
    }

    /**
     * 获取用户权限信息
     *
     * @param userId 用户ID
     * @return 用户权限DTO对象
     */
    @Override
    public UserPermissionDTO getUserPermission(Integer userId) {
        UserEntity userEntity = userService.getById(userId);
        if (Objects.isNull(userEntity)) {
            return new UserPermissionDTO();
        }
        List<AuthorityEntity> permissions = authorityService.getPermissionsByUserId(userId);
        return UserInfoConvert.INSTANCE.convertUserPermissionList(userEntity, permissions);
    }

    /**
     * 为用户添加经验值
     *
     * @param userId          用户ID
     * @param experienceValue 要添加的经验值
     */
    @Override
    public void addExperience(Integer userId, Integer experienceValue) {
        UserEntity children = userService.getById(userId);
        String device = userDeviceServiceApi.getDeviceByUserId(userId);
        UserExtendEntity userExtend = userExtendService.extraPoints(userId, experienceValue);
        Integer parentId = userInfoServiceApi.getParentIdByChildrenId(children.getId());
        UserCoinAccountRespDTO userCoinAccount = coinAccountServiceApi.getUserCoinAccount(parentId);
        pushUpdateChildrenInfoMessage(children, userExtend, device, userId, userCoinAccount);
    }

    /**
     * 获取孩子信息
     *
     * @param userId 孩子用户ID
     * @return 孩子信息DTO对象
     */
    @Override
    public ChildrenInfoDTO getChildrenInfo(Integer userId) {
        UserEntity children = userService.getById(userId);
        UserExtendEntity userExtend = userExtendService.getUserExtendByUserId(userId);
        GradeEntity grade = gradeService.getById(userExtend.getGradeId());
        LevelEntity level = levelService.getById(userExtend.getLevelId());
        Integer parentId = userRelationService.getParentIdByChildrenId(userId);
        UserCoinAccountRespDTO userCoinAccount = coinAccountServiceApi.getUserCoinAccount(parentId);
        return UserInfoConvert.INSTANCE.toChildrenInfoDTO(children.getId(),
                children.getNickName(),
                grade.getGrade(),
                children.getAvatar(),
                level.getName(),
                userExtend.getExperience(),
                level.getImageUrl(),
                userCoinAccount.getAvailableBalance().intValue());
    }

    /**
     * 获取孩子年级ID
     *
     * @param userId 孩子用户ID
     * @return 年级ID
     */
    @Override
    public Integer getChildrenGradeId(Integer userId) {
        UserExtendEntity userExtendByUserId = userExtendService.getUserExtendByUserId(userId);
        return userExtendByUserId.getGradeId();
    }

    /**
     * 保存用户信息
     *
     * @param userInfoDTO 用户信息DTO对象
     * @return 用户ID，如果用户已存在则返回已存在的用户ID
     */
    @Override
    public Integer save(UserInfoDTO userInfoDTO) {
        // 根据UnionId判断用户是否已存在
        if (StringUtils.hasText(userInfoDTO.getUnionId())) {
            UserAuthEntity userAuthEntity = userAuthService.getOneByUnionId(userInfoDTO.getUnionId());
            if (Objects.nonNull(userAuthEntity)) {
                log.info("用户已存在，请勿重复添加");
                return userAuthEntity.getId();
            }
            return save0(userInfoDTO);
        }
        // 根据OpenId判断用户是否已存在
        if (StringUtils.hasText(userInfoDTO.getOpenId())) {
            UserAuthEntity one = userAuthService.getOneByOpenId(userInfoDTO.getOpenId());
            if (Objects.nonNull(one)) {
                log.info("用户已存在，请勿重复添加");
                return one.getId();
            }
            return save0(userInfoDTO);
        }
        return null;
    }

    @Override
    public boolean updateUserInfoAndAssignRole(UserInfoDTO userInfoDTO) {
        UserEntity UserEntity = UserInfoConvert.INSTANCE.convertOne(userInfoDTO);
        userRoleService.assignUserRoleByRoleCode(UserEntity.getId(), userInfoDTO.getRoleCode().getCode());
        return userService.updateById(UserEntity);
    }

    @Override
    public boolean updateUserInfo(UserInfoDTO userInfoDTO) {
        UserEntity UserEntity = UserInfoConvert.INSTANCE.convertOne(userInfoDTO);
        return userService.updateById(UserEntity);
    }

    @Override
    public Integer addUserInfoAndAssignRole(UserInfoDTO userInfoDTO) {
        UserEntity userEntity = UserInfoConvert.INSTANCE.convertOne(userInfoDTO);
        userEntity.setPassword(CommonUtils.encryptPassword(userInfoDTO.getPassword()));
        boolean saved = userService.save(userEntity);
        log.info("保存用户信息：{}", saved);
        if(saved){
            userRoleService.assignUserRoleByRoleCode(userEntity.getId(), userInfoDTO.getRoleCode().getCode());
            return userEntity.getId();
        }
        throw new CommonException(ResultCodeEnum.USER_SAVE_ERROR);
    }

    @Override
    public Integer getParentIdByChildrenId(Integer childrenId) {
        return userRelationService.getParentIdByChildrenId(childrenId);
    }

    @Override
    public List<UserInfoDTO> listByMobile(String mobile) {
        List<UserEntity> userList = userService.list(new LambdaQueryWrapper<UserEntity>()
                .like(UserEntity::getMobile, mobile));
        return UserInfoConvert.INSTANCE.convertList(userList);
    }

    @Override
    public UserInfoDTO getUserByMobile(String mobile) {
        UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getMobile, mobile));
        return UserInfoConvert.INSTANCE.convertOne(user);
    }

    /**
     * 根据用户ID列表获取用户信息
     *
     * @param userIds
     * @return
     */
    @Override
    public List<UserDeviceDTO> listByIds(List<Integer> userIds) {
        List<UserEntity> userList = userService.listByIds(userIds);
        return UserInfoConvert.INSTANCE.convertUserDeviceList(userList);
    }

    /**
     * 根据用户ID获取用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserInfoDTO getByUserId(Integer userId) {
        UserEntity userEntity = userService.getById(userId);
        return UserInfoConvert.INSTANCE.convertOne(userEntity);
    }

    @Override
    public Integer saveDefaultChildrenUser() {
        UserEntity userEntity = new UserEntity();
        userService.save(userEntity);
        userRoleService.assignUserRoleByRoleCode(userEntity.getId(), RoleEnum.CHILDREN.getCode());
        log.info("注册默认Children User:{}", userEntity);
        return userEntity.getId();
    }

    @Override
    public Integer checkUserInfo(Integer userId) {
        UserExtendEntity byUserId = userExtendService.getByUserId(userId);
        if (Objects.isNull(byUserId)) {
            return IsInfoEnum.NO_INFO.getCode();
        }
        return IsInfoEnum.HAS_INFO.getCode();
    }

    @Override
    public Integer getUserIdByUserName(String userName) {
        UserEntity userEntity = userService.getOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserName, userName));
        AssertUtils.notNull(userEntity, ResultCodeEnum.USER_NOT_FOUND);
        return userEntity.getId();
    }

    /**
     * 推送更新孩子信息的MQ消息
     *
     * @param children         孩子用户实体对象
     * @param userExtendEntity 用户扩展信息实体对象
     * @param device           设备信息
     * @param userId           用户ID
     */
    public void pushUpdateChildrenInfoMessage(UserEntity children, UserExtendEntity userExtendEntity, String device, Integer userId, UserCoinAccountRespDTO userCoinAccount) {
        // 获取年级和等级信息
        GradeEntity grade = gradeService.getById(userExtendEntity.getGradeId());
        LevelEntity level = levelService.getById(userExtendEntity.getLevelId());
        MqUserInfoDTO userInfoDTO = UserInfoConvert.INSTANCE.toMqUserInfoDTO(children, userExtendEntity, grade, level, device);
        userInfoDTO.setExperience(CommonUtils.calculatePercentage(userExtendEntity.getExperience(), level.getPoint()));
        userInfoDTO.setCoinNumber(userCoinAccount.getAvailableBalance().intValue());
        String userJson = JSONUtil.toJsonStr(userInfoDTO);
        String topic = ImMqTopicEnum.USER_INFO.getTopic();
        String tag = UserInfoTopiTagEnum.UPDATE_CHILDREN_INFO.getTag();
        log.info("发送更新孩子[{}]MQ消息开始 Device: [{}],Topic:{}, Tag:{}", userId, device, topic, tag);
        mqProducer.sendMsg(topic, tag, device, userJson);
        log.info("发送更新孩子[{}]MQ消息成功 Device: [{}]", userId, device);
    }

    /**
     * 实际保存用户信息的私有方法
     *
     * @param userInfoDTO 用户信息DTO对象
     * @return 保存后的用户ID
     */
    private int save0(UserInfoDTO userInfoDTO) {
        UserEntity UserEntity = UserInfoConvert.INSTANCE.convertOne(userInfoDTO);
        boolean saveOrUpdate = userService.saveOrUpdate(UserEntity);
        log.info("保存用户信息:{}", saveOrUpdate);

        UserExtendEntity userExtend = new UserExtendEntity();
        userExtend.setUserId(UserEntity.getId());
        userExtendService.save(userExtend);

        return UserEntity.getId();
    }
}