package com.seer.teach.user.app.auth.service.strategy;


import com.seer.teach.common.enums.ResultCodeEnum;
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.mp.api.WechatMiniProgramApi;
import com.seer.teach.mp.api.resp.WxMiniProgramSessionDTO;
import com.seer.teach.user.app.auth.LoginType;
import com.seer.teach.user.app.auth.request.LoginParam;
import com.seer.teach.user.app.auth.service.LoginStrategy;
import com.seer.teach.user.app.auth.service.LoginUser;
import com.seer.teach.user.entity.UserAuthEntity;
import com.seer.teach.user.entity.UserEntity;
import com.seer.teach.user.entity.UserRelationEntity;
import com.seer.teach.user.service.IUserRelationService;
import com.seer.teach.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

@RequiredArgsConstructor
@Service
@Slf4j
public class WechatChildrenAccountLoginStrategy extends AbstractLoginStrategy implements LoginStrategy {

    private final IUserService userService;

    private final UserDeviceServiceApi userDeviceServiceApi;

    private final WechatMiniProgramApi wechatMiniProgramApi;

    private final IUserRelationService userRelationService;

    // 添加设备绑定检查开关，默认为true（开启检查）
    @Value("${zs.user.account.device.check.enabled:true}")
    private boolean deviceCheckEnabled;

    @Override
    public LoginType getType() {
        return LoginType.CHILDREN_ACCOUNT;
    }

    @Override
    public LoginUser authenticate(LoginParam request) {
        UserEntity accountUser =userService.getOneByMobile(request.getPhoneNumber());
        AssertUtils.notNull(accountUser, ResultCodeEnum.USERNAME_OR_PASSWORD_IS_ERROR);
        String password = CommonUtils.encryptPassword(request.getPassword());
        if (password.equals(accountUser.getPassword())) {
            WxMiniProgramSessionDTO miniProgramSessionDTO = wechatMiniProgramApi.code2Session(request.getJsCode());
            AssertUtils.notNull(miniProgramSessionDTO, ResultCodeEnum.WX_SESSION_CODE_USED_ERROR);
            // 使用开关控制是否检查设备绑定
            if (deviceCheckEnabled) {
                // 获取家长的信息，根据微信登录的用户信息，使用孩子登录前必须先家长登录，然后注册孩子账号，给孩子绑定设备
                UserRelationEntity userRelation = userRelationService.getUserRelationByRelationId(accountUser.getId());

                AssertUtils.notNull(userRelation, ResultCodeEnum.NOT_BIND_CHILDREN);

                List<UserAuthEntity> parentUserAuths = userAuthService.getUserAuthListByUserId(userRelation.getUserId());
                AssertUtils.notEmpty(parentUserAuths, ResultCodeEnum.USER_NOT_BIND_WECHAT);
                Optional<UserAuthEntity> any = parentUserAuths.stream().filter(userAuthEntity -> userAuthEntity.getOpenId().equals(miniProgramSessionDTO.getOpenid())).findAny();
                // 判断家长的账号和微信账号是否一致，如果不一致则说明该账号被其他人登录
                AssertUtils.isTrue(any.isPresent(), ResultCodeEnum.USER_DEVICE_USED);
            }
            String device = userDeviceServiceApi.getDeviceByUserId(accountUser.getId());

            AssertUtils.notEmpty(device, ResultCodeEnum.USER_NOT_BIND_DEVICE);

            UserAuthEntity userAuthEntity = userAuthService.getOneByOpenId(miniProgramSessionDTO.getOpenid());
            if (Objects.isNull(userAuthEntity)) {
                log.info("用户未绑定微信");
                boolean userAuthSaved = saveUserAuth(getType().getCode(), accountUser.getId(), miniProgramSessionDTO);
                log.info("保存用户授权信息：{}", userAuthSaved);
            }else {
                updateUserAuth(userAuthEntity);
            }
            log.info("用户[{}]登录成功", accountUser.getId());
            return new LoginUser(accountUser.getId());
        }
        throw new CommonException(ResultCodeEnum.USERNAME_OR_PASSWORD_IS_ERROR);
    }
}