package com.sikey.wa04.business.application.service.user;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONUtil;
import com.sikey.wa04.business.application.service.BaseService;
import com.sikey.wa04.business.application.service.UcloudService;
import com.sikey.wa04.business.infrastructure.dto.model.ChildRefModel;
import com.sikey.wa04.business.infrastructure.dto.model.GroupModel;
import com.sikey.wa04.business.infrastructure.dto.model.UserModel;
import com.sikey.wa04.business.infrastructure.dto.request.user.*;
import com.sikey.wa04.business.infrastructure.dto.response.user.RegisterOrNotResponse;
import com.sikey.wa04.business.infrastructure.repository.*;
import com.sikey.wa04.common.exception.BusinessException;
import com.sikey.wa04.common.exception.errors.Errors;
import com.sikey.wa04.common.interceptor.CurrentRequestUser;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户
 *
 * @author luoyangwei
 */
@Slf4j
@Service
public class UserService extends BaseService {

    @Resource
    private UserRepository userRepository;

    @Resource
    private UcloudService ucloudService;

    @Resource
    private ChildRefRepository childRefRepository;

    @Resource
    private ContactRepository contactRepository;

    @Resource
    private ChildRepository childRepository;

    @Resource
    private GroupRepository groupRepository;

    @Resource
    private GroupMemberRepository groupMemberRepository;

    @Resource
    private DeviceBindRepository deviceBindRepository;

    @Resource
    private ChildAlarmClockRepository childAlarmClockRepository;

    @Resource
    private ChildFenceRepository childFenceRepository;

    @Resource
    private ChildSchoolDisableRepository childSchoolDisableRepository;

    @Resource
    private MapTrajectoryLogRepository mapTrajectoryLogRepository;

    @Resource
    private MapTrajectoryRepository mapTrajectoryRepository;

    @Resource
    private MessageCenterRepository childMessageCenterRepository;

    @Resource
    private MessageRecvRepository messageRecvRepository;

    @Resource
    private MessageSendRepository messageSendRepository;

    @Resource
    private NotifyRepository notifyRepository;

    @Resource
    private PushRegistrationRepository pushRegistrationRepository;

    @Resource
    private RedisOperations<String, String> operations;

    private static final String SMS_CODE_PREFIX = "sms.code.%s";

    private static final String LOGIN_TOKEN = "login:token:%s";

    private static final String LOGIN_USER_ID = "login:user:id:%s";

    /**
     * 重置密码
     *
     * @param request 重置密码请求
     * @throws Exception 异常
     */
    public void resetPassword(ResetPasswordRequest request) throws Exception {
        Optional<UserModel> optional = userRepository.findById(CurrentRequestUser.get().getId());
        if (optional.isEmpty()) {
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), "用户不存在");
        }

        UserModel userModel = optional.get();
        if (!userModel.getPassword().equals(SecureUtil.md5(request.oldPassword()))) {
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), "旧密码错误");
        }

        //密码正确就修改密码
        userModel.setPassword(MD5.create().digestHex(request.newPassword()));
        userRepository.save(userModel);
        log.info("用户 {} 修改密码成功", userModel.getId());
    }

    /**
     * 找回密码
     *
     * @param request 找回密码请求
     * @throws Exception 异常
     */
    public void retrievePassword(RetrievePasswordRequest request) throws Exception {
        if (ucloudService.validation(request.phoneNumber(), request.areaCode(), request.captcha())) {
            UserModel userModel = userRepository.findByPhoneNumberAndAreaCode(request.phoneNumber(), request.areaCode());

            if (Objects.isNull(userModel)) {
                throw Errors.MOBILE_PHONE_NUMBER_NOT_REGISTERED.getException();
            } else if (Objects.nonNull(userModel.getIsRegistered()) && !userModel.getIsRegistered()) {
                throw Errors.MOBILE_PHONE_NUMBER_NOT_REGISTERED.getException();
            }

            userModel.setPassword(MD5.create().digestHex(request.newPassword()));
            userRepository.save(userModel);

            // 删除验证码
            String key = String.format(SMS_CODE_PREFIX, request.areaCode() + request.phoneNumber());
            operations.delete(key);

            log.info("用户 {} 找回密码成功", userModel.getId());
        } else {
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), "验证码错误");
        }
    }

    public void updatePassword(UpdatePasswordRequest request) throws Exception {
        UserModel userModel = userRepository.findByEmail(request.email());
        if (userModel == null) {
            throw Errors.USER_NOT_FOUND.getException();
        }
        userModel.setPassword(SecureUtil.md5(request.password()));
        userRepository.save(userModel);
        log.info("用户 {} 直接修改密码成功", userModel.getId());
    }

    /**
     * 注销账号
     *
     * @param request 注销请求
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void unregister(UnregisterRequest request) throws Exception {
        String userId = CurrentRequestUser.get().getId();
        Optional<UserModel> optional = userRepository.findById(userId);
        if (optional.isEmpty()) {
            throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "用户不存在");
        }
        UserModel userModel = optional.get();

        if (Objects.isNull(userModel.getPassword())) {
            throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "密码是空");
        }
        if (!userModel.getPassword().equals(SecureUtil.md5(request.password()))) {
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), "密码错误");
        }


        // 儿童
        List<String> childIdList = childRefRepository.findByUserId(userId).stream().map(ChildRefModel::getChildId).toList();

        // 用户身份
        // Integer identity = childRefRepository.findByUserId(userId).stream().map(ChildRefModel::getIdentity).findFirst().orElseThrow(() -> new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "不存在用户身份"));
        // 群组
        List<String> groupIdList = groupRepository.findIdByChildIdIn(childIdList).stream().map(GroupModel::getId).collect(Collectors.toList());
        /*if (identity.intValue() == IdentityEnum.IDENTITY_ADMIN.getValue() || identity.intValue() == IdentityEnum.IDENTITY_SUPER_ADMIN.getValue()) {
            // 管理员业务
            // 儿童
            childRepository.deleteAllById(childIdList);

            // 用户
            childRefRepository.deleteByUserId(userId);

            // 儿童通讯录
            contactRepository.deleteByRefIdIn(childIdList);
            // 用户
            contactRepository.deleteByRefId(userId);
            // 儿童通讯录
            contactRepository.deleteByChildIdIn(childIdList);

            groupRepository.deleteAllById(groupIdList);
            // 群组成员
            groupMemberRepository.deleteByGroupIdIn(groupIdList);
            // 手表儿童
            deviceBindRepository.deleteByChildIdIn(childIdList);
            // 小孩闹钟
            childAlarmClockRepository.deleteByChildIdIn(childIdList);
            // 小孩围栏
            childFenceRepository.deleteByChildIdIn(childIdList);
            // 小孩上课禁用
            childSchoolDisableRepository.deleteByChildIdIn(childIdList);

            // 小孩消息中心
            childMessageCenterRepository.deleteByChildrenIdIn(childIdList);

            // 小孩消息收信箱
            messageRecvRepository.deleteByRecvIdInOrSendIdIn(childIdList, childIdList);
            // 用户消息收件箱
            messageRecvRepository.deleteByRecvIdInOrSendIdIn(List.of(userId), List.of(userId));

            // 小孩消息发送
            messageSendRepository.deleteBySendIdIn(childIdList);
            // 小孩通知
            notifyRepository.deleteBySenderInOrReceiverIn(childIdList, childIdList);
        }else {
            // 儿童联系人
            childRefRepository.deleteByChildIdInAndUserId(childIdList,userId);
            // 儿童通讯录
            contactRepository.deleteByChildIdInAndRefId(childIdList,userId);
            // 群组成员
            groupMemberRepository.deleteByGroupIdInAndRefId(groupIdList,userId);
        }*/

        // 儿童联系人
        childRefRepository.deleteByChildIdInAndUserId(childIdList, userId);
        // 儿童通讯录
        contactRepository.deleteByChildIdInAndRefId(childIdList, userId);
        // 群组成员
        groupMemberRepository.deleteByGroupIdInAndRefId(groupIdList, userId);

        // 用户推送
        pushRegistrationRepository.deleteByUserId(userId);
        // 用户
        userRepository.deleteById(userId);

        // 删除旧的token
        String existingToken = operations.opsForValue().get(String.format(LOGIN_USER_ID, userModel.getId()));
        if (StrUtil.isNotBlank(existingToken)) {
            operations.delete(String.format(LOGIN_TOKEN, existingToken));
            operations.delete(String.format(LOGIN_USER_ID, userModel.getId()));
        }

        log.info("[注销账号]成功，用户编码：{}，儿童集合：{}", userId, JSONUtil.toJsonPrettyStr(childIdList));
    }

    /**
     * 是否注册
     *
     * @param smsCodeRequest 注册
     * @return
     */
    public RegisterOrNotResponse registerOrNot(SMSCodeRequest smsCodeRequest) {
        UserModel userModel = userRepository.findByPhoneNumberAndAreaCode(smsCodeRequest.phoneNumber(), smsCodeRequest.areaCode());
        RegisterOrNotResponse registerOrNotResponse = new RegisterOrNotResponse();
        registerOrNotResponse.setRegistered(Objects.nonNull(userModel) && userModel.getIsRegistered());
        return registerOrNotResponse;
    }

}
