package rd.service.user;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import rd.dao.mapper.user.StudentInfoMapper;
import rd.dao.mapper.user.TeacherInfoMapper;
import rd.data.code.ServiceCode;
import rd.data.db.table.StudentInfo;
import rd.data.db.table.TeacherInfo;
import rd.exception.ServiceException;

import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserInfoService {

    private static final Cache<Long, Object> userInfoCache = Caffeine.newBuilder()
            .expireAfterWrite(2, TimeUnit.DAYS)
            .initialCapacity(256)
            .maximumSize(2048)
            .build();

    private final StudentInfoMapper studentInfoMapper;

    private final TeacherInfoMapper teacherInfoMapper;

    public UserInfoService(StudentInfoMapper studentInfoMapper, TeacherInfoMapper teacherInfoMapper) {
        this.studentInfoMapper = studentInfoMapper;
        this.teacherInfoMapper = teacherInfoMapper;
    }

    public void invalidateCache(Long id) {
        userInfoCache.invalidate(id);
    }

    public StudentInfo getAsStudent(Long id, boolean useCache) {
        Object info = userInfoCache.getIfPresent(id);
        if (useCache && info != null) {
            log.debug("使用缓存的用户信息，用户id：{}", id);
            return (StudentInfo) info;
        }

        info = studentInfoMapper.selectOne(new QueryWrapper<StudentInfo>()
                .eq("id", id)
                .eq("deleted", false)
        );

        if (info == null) {
            throw ServiceException.error(
                    ServiceCode.UserNotExists,
                    "账号信息存在，但是用户信息不存在，这种情况不应该出现，请联系管理员：lensfrex@qq.com"
            );
        }

        userInfoCache.put(id, info);
        return (StudentInfo) info;
    }

    public StudentInfo getAsStudent(Long id) {
        return getAsStudent(id, true);
    }

    public TeacherInfo getAsTeacher(Long id, boolean useCache) {
        Object info = userInfoCache.getIfPresent(id);
        if (useCache && info != null) {
            log.debug("使用缓存的用户信息，用户id：{}", id);
            return (TeacherInfo) info;
        }

        info = teacherInfoMapper.selectOne(new QueryWrapper<TeacherInfo>()
                .select("id", "name")
                .eq("id", id)
                .eq("deleted", false)
        );

        userInfoCache.put(id, info);
        return (TeacherInfo) info;
    }

    public TeacherInfo getAsTeacher(Long id) {
        return getAsTeacher(id, true);
    }

    public List<TeacherInfo> getAsTeacher(List<Long> idList) {
        var cached = userInfoCache.getAll(idList, keyList -> {
            var teachers = teacherInfoMapper.selectList(new QueryWrapper<TeacherInfo>()
                    .in("id", idList)
                    .eq("deleted", false)
            );

            Map<Long, TeacherInfo> teacherInfoMap = new HashMap<>(teachers.size());
            for (TeacherInfo teacher : teachers) {
                teacherInfoMap.put(teacher.getId(), teacher);
            }
            return teacherInfoMap;
        });

        return cached.values().stream().map(obj -> (TeacherInfo) obj).toList();
    }
}
