package com.schisandra.auth.domain.service.impl;


import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.schisandra.auth.common.entity.Result;
import com.schisandra.auth.common.enums.IsDeletedFlagEnum;
import com.schisandra.auth.common.enums.UserRoleEnum;
import com.schisandra.auth.common.enums.UserStatusEnum;
import com.schisandra.auth.common.redis.RedisUtil;
import com.schisandra.auth.domain.bo.SchisandraAuthSocialUserBO;
import com.schisandra.auth.domain.bo.SchisandraAuthSocialUserMapperBO;
import com.schisandra.auth.domain.bo.SchisandraAuthUserBO;
import com.schisandra.auth.domain.bo.SchisandraAuthUserRoleBO;
import com.schisandra.auth.domain.convert.SchisandraAuthSocialUserBOConverter;
import com.schisandra.auth.domain.convert.SchisandraAuthSocialUserMapperBOConverter;
import com.schisandra.auth.domain.convert.SchisandraAuthUserBOConverter;
import com.schisandra.auth.domain.convert.SchisandraAuthUserRoleBOConverter;
import com.schisandra.auth.domain.service.SchisandraAuthUserDomainService;
import com.schisandra.auth.infra.basic.entity.*;
import com.schisandra.auth.infra.basic.service.*;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 领域service实现了
 *
 * @author landaiqing
 * @since 2024-05-23 20:00:28
 */
@Service
@Slf4j
public class SchisandraAuthUserDomainServiceImpl implements SchisandraAuthUserDomainService {

    @Resource
    private SchisandraAuthUserService schisandraAuthUserService;
    @Resource
    private SchisandraAuthUserRoleService schisandraAuthUserRoleService;


    @Resource
    private SchisandraAuthSocialUserService schisandraAuthSocialUserService;

    @Resource
    private SchisandraAuthSocialUserMapperService schisandraAuthSocialUserMapperService;

    @Resource
    private SchisandraAuthRoleService schisandraAuthRoleService;


    private final String AUTH_PERMISSION_PREFIX = "auth.permission";

    private final String AUTH_ROLE_PREFIX = "auth.role";

    @Resource
    RedisUtil redisUtil;

    @Resource
    private SchisandraAuthRolePermissionService schisandraAuthRolePermissionService;

    @Resource
    private SchisandraAuthPermissionService schisandraAuthPermissionService;


    /**
     * @description: 注册用户
     * @param: [schisandraAuthUserBO]
     * @return: com.schisandra.auth.domain.bo.SchisandraAuthUserBO
     * @author zlg
     * @date: 2024/5/14 20:59
     */
    @Override
    public Boolean register(SchisandraAuthUserBO schisandraAuthUserBO) {
        SchisandraAuthUser authUser = SchisandraAuthUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserBO);
        if (schisandraAuthUserService.insert(authUser)) {
            SchisandraAuthUserRoleBO schisandraAuthUserRoleBO = new SchisandraAuthUserRoleBO();
            schisandraAuthUserRoleBO.setUserId(authUser.getId());
            schisandraAuthUserRoleBO.setRoleId(UserRoleEnum.NORMAL_USER.getCode());
            SchisandraAuthUserRole schisandraAuthUserRole = SchisandraAuthUserRoleBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserRoleBO);
            return schisandraAuthUserRoleService.insert(schisandraAuthUserRole) > 1;
        } else {
            return false;
        }


    }

    /**
     * @description: 登录
     * @param: [schisandraAuthUserBO]
     * @return: com.schisandra.auth.domain.bo.SchisandraAuthUserBO
     * @author: landaiqing
     * @date: 2024/5/31 1:22
     */
    @Override
    public SchisandraAuthUserBO login(SchisandraAuthUserBO schisandraAuthUserBO) {

        Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        Boolean emailMatch = pattern.matcher(schisandraAuthUserBO.getUserName()).matches();
        SchisandraAuthUser schisandraAuthUser;
        if (emailMatch) {
            schisandraAuthUser = schisandraAuthUserService.queryByEmail(schisandraAuthUserBO.getUserName());
        } else {
            schisandraAuthUser = schisandraAuthUserService.queryByPhone(schisandraAuthUserBO.getUserName());
        }
        if (schisandraAuthUser != null && schisandraAuthUserBO.getPassword() != null) {
            if (schisandraAuthUser.getPassword().equals(schisandraAuthUserBO.getPassword())) {
                return SchisandraAuthUserBOConverter.INSTANCE.convertEntityToBO(schisandraAuthUser);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * @param schisandraAuthUserBO
     * @return java.lang.Object
     * @description 更新用户信息
     * @author schisandra
     * @date 2024/3/21 23:14
     */
    @Override
    public Object update(SchisandraAuthUserBO schisandraAuthUserBO) {
        SchisandraAuthUser schisandraAuthUser = SchisandraAuthUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserBO);
        Integer count = schisandraAuthUserService.update(schisandraAuthUser);
        return count > 0;
    }


    /**
     * @param schisandraAuthUserBO
     * @return
     * @description 查询用户信息
     * @author msz
     * @date 2024/4/3 22:10
     */
    @Override
    public SchisandraAuthUserBO queryById(SchisandraAuthUserBO schisandraAuthUserBO) {
        SchisandraAuthUser schisandraAuthUser = schisandraAuthUserService.queryById(schisandraAuthUserBO.getId());
        SchisandraAuthUserBO schisandraAuthUserBO1 = SchisandraAuthUserBOConverter.INSTANCE.convertEntityToBO(schisandraAuthUser);
        return schisandraAuthUserBO1;
    }

    /**
     * @param schisandraAuthUserBO
     * @return java.lang.Object
     * @description 添加用户信息
     * @author msz
     * @date 2024/4/3 22:17
     */
    @Override
    public Object insert(SchisandraAuthUserBO schisandraAuthUserBO) {
        SchisandraAuthUser schisandraAuthUser = SchisandraAuthUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserBO);
        return schisandraAuthUserService.insert(schisandraAuthUser);
    }

    /**
     * @param id
     * @return java.lang.Object
     * @description 删除用户信息
     * @author msz
     * @date 2024/4/3 22:30
     */
    @Override
    public Object deleteById(Long id) {
        boolean flag = schisandraAuthUserService.deleteById(id);
        return flag;
    }

    /**
     * @description: 根据手机号查询用户信息
     * @param: [phone]
     * @return: java.lang.Boolean
     * @author: landaiqing
     * @date: 2024/5/29 21:41
     */
    @Override
    public SchisandraAuthUser queryByPhone(String phone) {
        return schisandraAuthUserService.queryByPhone(phone);
    }

    /**
     * @description: 根据第三方用户信息添加用户信息
     * @param: [data, type]
     * @return: void
     * @author: landaiqing
     * @date: 2024/5/26 17:35
     */
    @Override
    @Transactional
    public Result insertAuthUserByOauth(AuthUser data, String type) {
        String uuid = data.getUuid();
        AuthToken token = data.getToken();
        SchisandraAuthSocialUser authSocialUser = schisandraAuthSocialUserService.selectByUuidAndType(uuid, type);
        if (ObjectUtils.isNotEmpty(authSocialUser)) {
            // 如果用户登录过就更新社会用户信息表
            SchisandraAuthSocialUserBO schisandraAuthSocialUserBO = new SchisandraAuthSocialUserBO();
            schisandraAuthSocialUserBO.setAccessToken(token.getAccessToken());
            schisandraAuthSocialUserBO.setSource(data.getSource());
            schisandraAuthSocialUserBO.setUid(token.getUid());
            schisandraAuthSocialUserBO.setOpenId(token.getOpenId());
            schisandraAuthSocialUserBO.setCode(token.getCode());
            schisandraAuthSocialUserBO.setAccessCode(token.getAccessCode());
            schisandraAuthSocialUserBO.setExpireIn(token.getExpireIn());
            schisandraAuthSocialUserBO.setIdToken(token.getIdToken());
            schisandraAuthSocialUserBO.setMacAlgorithm(token.getMacAlgorithm());
            schisandraAuthSocialUserBO.setMacKey(token.getMacKey());
            schisandraAuthSocialUserBO.setOauthToken(token.getOauthToken());
            schisandraAuthSocialUserBO.setOauthTokenSecret(token.getOauthTokenSecret());
            schisandraAuthSocialUserBO.setRefreshToken(token.getRefreshToken());
            schisandraAuthSocialUserBO.setId(authSocialUser.getId());
            SchisandraAuthSocialUser schisandraAuthSocialUser = SchisandraAuthSocialUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthSocialUserBO);
            int update = schisandraAuthSocialUserService.updateByOauth(schisandraAuthSocialUser);
            if (update <= 0) {
                if (log.isInfoEnabled()) {
                    log.error("schisandraAuthSocialUserService.update fail, param:{}", JSONObject.toJSONString(schisandraAuthSocialUser));
                }
                return Result.fail("Social User update fail");
            }
            // 获取用户id
            SchisandraAuthSocialUserMapper schisandraAuthSocialUserMapper = new SchisandraAuthSocialUserMapper();
            schisandraAuthSocialUserMapper.setSocialUserId(authSocialUser.getId());
            SchisandraAuthSocialUserMapper result = schisandraAuthSocialUserMapperService.queryBySocialUserId(schisandraAuthSocialUserMapper);
            if (ObjectUtils.isEmpty(result)) {
                if (log.isInfoEnabled()) {
                    log.error("schisandraAuthSocialUserMapperService.queryByCondition fail, param:{}", JSONObject.toJSONString(schisandraAuthSocialUserMapper));
                }
                return Result.fail("Social Mapper is empty");
            }
            Long userId = result.getUserId();

            // redis存储用户角色与权限信息
            userInfoPersistence(userId);
            StpUtil.login(userId, SaLoginConfig.setToken(token.getAccessToken()));
        } else {
            // 插入用户信息表
            SchisandraAuthUserBO schisandraAuthUserBO = new SchisandraAuthUserBO();
            schisandraAuthUserBO.setAvatar(data.getAvatar());
            schisandraAuthUserBO.setBlog(data.getBlog());
            schisandraAuthUserBO.setEmail(data.getEmail());
            schisandraAuthUserBO.setCompany(data.getCompany());
            schisandraAuthUserBO.setGender(String.valueOf(data.getGender()));
            schisandraAuthUserBO.setIntroduce(data.getRemark());
            schisandraAuthUserBO.setLocation(data.getLocation());
            schisandraAuthUserBO.setNickName(data.getNickname());
            schisandraAuthUserBO.setUserName(data.getUsername());
            schisandraAuthUserBO.setStatus(UserStatusEnum.NORMAL.getCode());
            schisandraAuthUserBO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            SchisandraAuthUser schisandraAuthUser = SchisandraAuthUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserBO);
            int result = schisandraAuthUserService.insertAuthUserByOauth(schisandraAuthUser);
            if (result <= 0) {
                if (log.isInfoEnabled()) {
                    log.error("insertAuthUserByOauth fail, param:{}", JSONObject.toJSONString(schisandraAuthUser));
                }
                return Result.fail("insertAuthUserByOauth.insertAuthUserByOauth fail");
            }
            // 插入社会用户信息表
            SchisandraAuthSocialUserBO schisandraAuthSocialUserBO = new SchisandraAuthSocialUserBO();
            schisandraAuthSocialUserBO.setUuid(data.getUuid());
            schisandraAuthSocialUserBO.setAccessToken(token.getAccessToken());
            schisandraAuthSocialUserBO.setSource(data.getSource());
            schisandraAuthSocialUserBO.setUid(token.getUid());
            schisandraAuthSocialUserBO.setOpenId(token.getOpenId());
            schisandraAuthSocialUserBO.setCode(token.getCode());
            schisandraAuthSocialUserBO.setAccessCode(token.getAccessCode());
            schisandraAuthSocialUserBO.setExpireIn(token.getExpireIn());
            schisandraAuthSocialUserBO.setIdToken(token.getIdToken());
            schisandraAuthSocialUserBO.setMacAlgorithm(token.getMacAlgorithm());
            schisandraAuthSocialUserBO.setMacKey(token.getMacKey());
            schisandraAuthSocialUserBO.setOauthToken(token.getOauthToken());
            schisandraAuthSocialUserBO.setOauthTokenSecret(token.getOauthTokenSecret());
            schisandraAuthSocialUserBO.setRefreshToken(token.getRefreshToken());
            schisandraAuthSocialUserBO.setScope(token.getScope());
            schisandraAuthSocialUserBO.setTokenType(token.getTokenType());
            schisandraAuthSocialUserBO.setUnionId(token.getUnionId());
            schisandraAuthSocialUserBO.setStatus(UserStatusEnum.NORMAL.getCode());
            schisandraAuthSocialUserBO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            SchisandraAuthSocialUser schisandraAuthSocialUser = SchisandraAuthSocialUserBOConverter.INSTANCE.convertBOToEntity(schisandraAuthSocialUserBO);
            int resultCode = schisandraAuthSocialUserService.insertAuthSocialUserByOauth(schisandraAuthSocialUser);
            if (resultCode <= 0) {
                if (log.isInfoEnabled()) {
                    log.error("insertAuthSocialUserByOauth fail, param:{}", JSONObject.toJSONString(schisandraAuthSocialUserBO));
                }
                return Result.fail("schisandraAuthSocialUserService insert fail");
            }

            // 建立用户与社会信息映射关系
            Long authUserId = schisandraAuthUser.getId();
            Long authSocialUserId = schisandraAuthSocialUser.getId();
            SchisandraAuthSocialUserMapperBO schisandraAuthSocialUserMapperBO = new SchisandraAuthSocialUserMapperBO();
            schisandraAuthSocialUserMapperBO.setUserId(authUserId);
            schisandraAuthSocialUserMapperBO.setSocialUserId(authSocialUserId);
            schisandraAuthSocialUserMapperBO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            SchisandraAuthSocialUserMapper schisandraAuthSocialUserMapper = SchisandraAuthSocialUserMapperBOConverter.INSTANCE.convertBOToEntity(schisandraAuthSocialUserMapperBO);
            int code = schisandraAuthSocialUserMapperService.insertAuthSocialUserMapperByOauth(schisandraAuthSocialUserMapper);
            if (code <= 0) {
                if (log.isInfoEnabled()) {
                    log.error("insertAuthSocialUserMapperByOauth fail, param:{}", JSONObject.toJSONString(schisandraAuthSocialUserMapperBO));
                }
                return Result.fail("insertAuthSocialUserMapperByOauth fail");
            }
            // 建立用户与角色映射关系
            SchisandraAuthUserRoleBO schisandraAuthUserRoleBO = new SchisandraAuthUserRoleBO();
            schisandraAuthUserRoleBO.setUserId(authUserId);
            schisandraAuthUserRoleBO.setRoleId(UserRoleEnum.NORMAL_USER.getCode());
            schisandraAuthUserRoleBO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            SchisandraAuthUserRole schisandraAuthUserRole = SchisandraAuthUserRoleBOConverter.INSTANCE.convertBOToEntity(schisandraAuthUserRoleBO);
            int insert = schisandraAuthUserRoleService.insert(schisandraAuthUserRole);
            if (insert <= 0) {
                if (log.isInfoEnabled()) {
                    log.error("insertUserRole fail, param:{}", JSONObject.toJSONString(schisandraAuthUserRole));
                }
                return Result.fail("insertUserRole fail");
            }

            // redis存储用户角色与权限信息
            userInfoPersistence(authUserId);

            StpUtil.login(authUserId, SaLoginConfig.setToken(token.getAccessToken()));
        }
        return Result.ok();

    }

    /**
     * @description: 用户信息持久化
     * @param: [authUserId]
     * @return: void
     * @author: landaiqing
     * @date: 2024/6/2 0:37
     */
    private void userInfoPersistence(Long authUserId) {
        // 查询用户角色并存入redis
        SchisandraAuthRole schisandraAuthRole = schisandraAuthRoleService.queryByRoleId(UserRoleEnum.NORMAL_USER.getCode());
        String roleKey = redisUtil.buildKey(AUTH_ROLE_PREFIX, String.valueOf(authUserId));
        List<SchisandraAuthRole> roleList = new LinkedList<>();
        roleList.add(schisandraAuthRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));

        // 查询用户权限并存入redis
        SchisandraAuthRolePermission schisandraAuthRolePermission = new SchisandraAuthRolePermission();
        schisandraAuthRolePermission.setRoleId(UserRoleEnum.NORMAL_USER.getCode());
        List<SchisandraAuthRolePermission> rolePermissionList = schisandraAuthRolePermissionService.queryByRoleId(schisandraAuthRolePermission);
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(SchisandraAuthRolePermission::getPermissionId).collect(Collectors.toList());
        List<SchisandraAuthPermission> permissionList = schisandraAuthPermissionService.queryListByIds(permissionIdList);
        String permissionKey = redisUtil.buildKey(AUTH_PERMISSION_PREFIX, String.valueOf(authUserId));
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));
    }

}
