package cn.iocoder.byzs.module.web.service.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.byzs.framework.common.enums.CommonStatusEnum;
import cn.iocoder.byzs.framework.common.util.collection.CollectionUtils;
import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
import cn.iocoder.byzs.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.byzs.module.system.controller.admin.invitecode.vo.InviteCodeSaveReqVO;
import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
import cn.iocoder.byzs.module.system.dal.dataobject.invitecode.InviteCodeDO;
import cn.iocoder.byzs.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.byzs.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.byzs.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
import cn.iocoder.byzs.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.byzs.module.system.service.invitecode.InviteCodeService;
import cn.iocoder.byzs.module.system.service.permission.PermissionService;
import cn.iocoder.byzs.module.system.service.permission.RoleService;
import cn.iocoder.byzs.module.system.service.user.AdminUserServiceImpl;
import cn.iocoder.byzs.module.system.service.userwebexpiretime.UserWebExpireTimeService;
import cn.iocoder.byzs.module.web.controller.admin.user.vo.WebUserVO;
import cn.iocoder.byzs.module.web.service.login.WebLoginServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.byzs.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.byzs.module.system.enums.ErrorCodeConstants.USER_CODE_FAILURE;
import static cn.iocoder.byzs.module.system.enums.ErrorCodeConstants.USER_CODE_USED;

@Service
public class WebUserInfoServiceImpl {
    @Resource
    private AdminUserServiceImpl userService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private InviteCodeService inviteCodeService;
    @Resource
    private WebLoginServiceImpl loginService;
    @Resource
    private RoleService roleService;
    @Resource
    private UserWebExpireTimeService userWebExpireTimeService;
    @Resource
    private WebLoginServiceImpl webLoginServiceImpl;
    @Resource
    private UserRoleMapper userRoleMapper;

    @Transactional(rollbackFor = Exception.class)
    public Boolean activateInviteCode(String inviteCode) {

        //校验邀请码
        InviteCodeDO inviteCodeDo = inviteCodeService.getUnusedInviteCode(inviteCode);
        if (inviteCodeDo == null) {
            throw exception(USER_CODE_FAILURE);
        }
        if(!"0".equals(inviteCodeDo.getStatus())){
            throw exception(USER_CODE_USED);
        }
        Set<Long> codeRoleIds = Arrays.stream(inviteCodeDo.getRoleIds().split(","))
                .map(s ->Long.parseLong(s.trim())).collect(Collectors.toSet());

        //补充用户角色
        Long userId = WebFrameworkUtils.getLoginUserId();
        AdminUserDO user = userService.getUser(userId);
//        permissionService.assignUserRole(userId, codeRoleIds);

        // 获得角色拥有角色编号
        Set<Long> dbRoleIds = convertSet(userRoleMapper.selectListByUserId(userId),
                UserRoleDO::getRoleId);
        Collection<Long> createRoleIds = CollUtil.subtract(codeRoleIds, dbRoleIds);
        if (!CollectionUtil.isEmpty(createRoleIds)) {
            userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> {
                UserRoleDO entity = new UserRoleDO();
                entity.setUserId(userId);
                entity.setRoleId(roleId);
                return entity;
            }));
        }

        // 更新邀请码为已使用
        inviteCodeService.updateInviteCode(new InviteCodeSaveReqVO()
                .setId(inviteCodeDo.getId())
                .setUseUserId(userId)
                .setUseUserTenantId(user.getTenantId())
                .setUseTime(LocalDateTime.now())
                .setExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()))
                .setStatus("1"));

        // 更新用户web过期时间
        List<RoleDO> roleList = roleService.getRoleList(codeRoleIds);
        roleList.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
        Set<String> roleWebMap = new HashSet<>();
        roleList.forEach(role -> {
            if(role.getDataScopeWebRoute() != null && !role.getDataScopeWebRoute().isEmpty()){
                roleWebMap.addAll(role.getDataScopeWebRoute());
            }
        });

        //当前用户web过期时间
        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(userId);
        if (userWebExpireTime != null) {
            if(roleWebMap.contains("course")){
                LocalDateTime courseExpireTime = userWebExpireTime.getCourseExpireTime();
                if(courseExpireTime == null){
                    courseExpireTime = LocalDateTime.now();
                }
                userWebExpireTime.setCourseExpireTime(courseExpireTime.plusDays(inviteCodeDo.getValidTime()));
            }
            if(roleWebMap.contains("blockly")){
                LocalDateTime blocklyExpireTime = userWebExpireTime.getBlocklyExpireTime();
                if(blocklyExpireTime == null){
                    blocklyExpireTime = LocalDateTime.now();
                }
                userWebExpireTime.setBlocklyExpireTime(blocklyExpireTime.plusDays(inviteCodeDo.getValidTime()));
            }
            if (roleWebMap.contains("aiCourse")){
                LocalDateTime aiCourseExpireTime = userWebExpireTime.getAiCourseExpireTime();
                if(aiCourseExpireTime == null){
                    aiCourseExpireTime = LocalDateTime.now();
                }
                userWebExpireTime.setAiCourseExpireTime(aiCourseExpireTime.plusDays(inviteCodeDo.getValidTime()));
            }

            // 更新用户web过期时间
            userWebExpireTimeService.updateUserWebExpireTime(BeanUtils.toBean(userWebExpireTime, UserWebExpireTimeSaveReqVO.class));
        }else{
            // 创建用户web过期时间
            UserWebExpireTimeSaveReqVO userWebExpireTimeDO = new UserWebExpireTimeSaveReqVO().setUserId(userId);
            if(roleWebMap.contains("course")){
                userWebExpireTimeDO.setCourseExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
            }
            if(roleWebMap.contains("blockly")){
                userWebExpireTimeDO.setBlocklyExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
            }
            if (roleWebMap.contains("aiCourse")){
                userWebExpireTimeDO.setAiCourseExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
            }
            userWebExpireTimeService.createUserWebExpireTime(userWebExpireTimeDO);
        }

        // 用户id
        return true;
    }

    // 中文年月日格式
    private static final DateTimeFormatter CHINESE_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy年MM月dd日");

    public WebUserVO getUserInfo(Long userId) {
        AdminUserDO user = userService.getUser(userId);
        WebUserVO webUserVO = BeanUtils.toBean(user, WebUserVO.class);

        //平台角色路由
        Set<String> roleRouteSet = webLoginServiceImpl.getRoleRoute(userId);
        webUserVO.setRoleRouteSet(roleRouteSet);

        //是否是注册用户
        List<InviteCodeDO> inviteCodes = inviteCodeService.getInviteCodeByUserId(userId);
        webUserVO.setIsRegister(!inviteCodes.isEmpty());
        if (inviteCodes.isEmpty()) {
            return webUserVO;
        }

        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(userId);
        if (userWebExpireTime != null) {
            // 将LocalDateTime格式化为中文年月日字符串
            if (userWebExpireTime.getCourseExpireTime() != null) {
                webUserVO.setCourseExpireTime(userWebExpireTime.getCourseExpireTime());
            }
            if (userWebExpireTime.getBlocklyExpireTime() != null) {
                webUserVO.setBlocklyExpireTime(userWebExpireTime.getBlocklyExpireTime());
            }
            if (userWebExpireTime.getAiCourseExpireTime() != null) {
                webUserVO.setAiCourseExpireTime(userWebExpireTime.getAiCourseExpireTime());
            }
        }

        // 用户id
        return webUserVO;
    }
}