package com.nanri.aiimage.modules.ziniao.memory.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nanri.aiimage.common.exception.BusinessException;
import com.nanri.aiimage.modules.ziniao.memory.mapper.ZiniaoMemoryStoreMapper;
import com.nanri.aiimage.modules.ziniao.memory.model.entity.ZiniaoMemoryStoreEntity;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ZiniaoMemoryStoreService {

    private final ZiniaoMemoryStoreMapper ziniaoMemoryStoreMapper;
    private final ObjectMapper objectMapper;

    public <T> Optional<T> get(String cacheType, String cacheKey, Class<T> valueType) {
        ZiniaoMemoryStoreEntity entity = findOne(cacheType, cacheKey);
        if (entity == null) {
            return Optional.empty();
        }
        if (isExpired(entity)) {
            ziniaoMemoryStoreMapper.deleteById(entity.getId());
            return Optional.empty();
        }
        try {
            return Optional.ofNullable(objectMapper.readValue(entity.getPayloadJson(), valueType));
        } catch (Exception ex) {
            throw new BusinessException("读取紫鸟记忆存储失败");
        }
    }

    public <T> Optional<T> get(String cacheType, String cacheKey, JavaType javaType) {
        ZiniaoMemoryStoreEntity entity = findOne(cacheType, cacheKey);
        if (entity == null) {
            return Optional.empty();
        }
        if (isExpired(entity)) {
            ziniaoMemoryStoreMapper.deleteById(entity.getId());
            return Optional.empty();
        }
        try {
            @SuppressWarnings("unchecked")
            T value = (T) objectMapper.readValue(entity.getPayloadJson(), javaType);
            return Optional.ofNullable(value);
        } catch (Exception ex) {
            throw new BusinessException("读取紫鸟记忆存储失败");
        }
    }

    public <E> Optional<List<E>> getList(String cacheType, String cacheKey, Class<E> elementType) {
        JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, elementType);
        return get(cacheType, cacheKey, type);
    }

    public <T> List<T> listByType(String cacheType, Class<T> valueType, int limit) {
        String normalizedType = normalizeRequired(cacheType, "cacheType 不能为空");
        int safeLimit = Math.max(limit, 1);
        List<ZiniaoMemoryStoreEntity> entities = ziniaoMemoryStoreMapper.selectList(new LambdaQueryWrapper<ZiniaoMemoryStoreEntity>()
                .eq(ZiniaoMemoryStoreEntity::getCacheType, normalizedType)
                .orderByAsc(ZiniaoMemoryStoreEntity::getCacheKey)
                .last("LIMIT " + safeLimit));
        if (entities.isEmpty()) {
            return List.of();
        }
        LocalDateTime now = LocalDateTime.now();
        return entities.stream()
                .filter(entity -> entity.getExpiresAt() != null && entity.getExpiresAt().isAfter(now))
                .map(entity -> deserialize(entity.getPayloadJson(), valueType))
                .filter(Objects::nonNull)
                .toList();
    }

    @Transactional
    public void put(String cacheType, String cacheKey, Object payload, Duration ttl) {
        String normalizedType = normalizeRequired(cacheType, "cacheType 不能为空");
        String normalizedKey = normalizeRequired(cacheKey, "cacheKey 不能为空");
        if (ttl == null || ttl.isZero() || ttl.isNegative()) {
            throw new BusinessException("ttl 不合法");
        }
        String payloadJson;
        try {
            payloadJson = objectMapper.writeValueAsString(payload);
        } catch (Exception ex) {
            throw new BusinessException("写入紫鸟记忆存储失败");
        }
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expiresAt = now.plusSeconds(ttl.getSeconds());
        ZiniaoMemoryStoreEntity entity = findOne(normalizedType, normalizedKey);
        if (entity == null) {
            entity = new ZiniaoMemoryStoreEntity();
            entity.setCacheType(normalizedType);
            entity.setCacheKey(normalizedKey);
            entity.setPayloadJson(payloadJson);
            entity.setExpiresAt(expiresAt);
            entity.setCreatedAt(now);
            entity.setUpdatedAt(now);
            ziniaoMemoryStoreMapper.insert(entity);
            return;
        }
        entity.setPayloadJson(payloadJson);
        entity.setExpiresAt(expiresAt);
        entity.setUpdatedAt(now);
        ziniaoMemoryStoreMapper.updateById(entity);
    }

    @Transactional
    public void delete(String cacheType, String cacheKey) {
        ZiniaoMemoryStoreEntity entity = findOne(cacheType, cacheKey);
        if (entity != null) {
            ziniaoMemoryStoreMapper.deleteById(entity.getId());
        }
    }

    @Transactional
    public int deleteByType(String cacheType, int limit) {
        String normalizedType = normalizeRequired(cacheType, "cacheType 不能为空");
        int safeLimit = Math.max(limit, 1);
        List<ZiniaoMemoryStoreEntity> entities = ziniaoMemoryStoreMapper.selectList(new LambdaQueryWrapper<ZiniaoMemoryStoreEntity>()
                .eq(ZiniaoMemoryStoreEntity::getCacheType, normalizedType)
                .orderByAsc(ZiniaoMemoryStoreEntity::getCacheKey)
                .last("LIMIT " + safeLimit));
        if (entities.isEmpty()) {
            return 0;
        }
        int deleted = 0;
        for (ZiniaoMemoryStoreEntity entity : entities) {
            deleted += ziniaoMemoryStoreMapper.deleteById(entity.getId());
        }
        return deleted;
    }

    @Transactional
    public int deleteExpired(int limit) {
        int safeLimit = Math.max(limit, 1);
        List<ZiniaoMemoryStoreEntity> expired = ziniaoMemoryStoreMapper.selectList(new LambdaQueryWrapper<ZiniaoMemoryStoreEntity>()
                .lt(ZiniaoMemoryStoreEntity::getExpiresAt, LocalDateTime.now())
                .orderByAsc(ZiniaoMemoryStoreEntity::getExpiresAt)
                .last("LIMIT " + safeLimit));
        if (expired.isEmpty()) {
            return 0;
        }
        int deleted = 0;
        for (ZiniaoMemoryStoreEntity entity : expired) {
            deleted += ziniaoMemoryStoreMapper.deleteById(entity.getId());
        }
        return deleted;
    }

    private ZiniaoMemoryStoreEntity findOne(String cacheType, String cacheKey) {
        String normalizedType = normalizeRequired(cacheType, "cacheType 不能为空");
        String normalizedKey = normalizeRequired(cacheKey, "cacheKey 不能为空");
        return ziniaoMemoryStoreMapper.selectOne(new LambdaQueryWrapper<ZiniaoMemoryStoreEntity>()
                .eq(ZiniaoMemoryStoreEntity::getCacheType, normalizedType)
                .eq(ZiniaoMemoryStoreEntity::getCacheKey, normalizedKey)
                .last("LIMIT 1"));
    }

    private <T> T deserialize(String payloadJson, Class<T> valueType) {
        try {
            return objectMapper.readValue(payloadJson, valueType);
        } catch (Exception ex) {
            throw new BusinessException("读取紫鸟记忆存储失败");
        }
    }

    private boolean isExpired(ZiniaoMemoryStoreEntity entity) {
        return entity.getExpiresAt() == null || !entity.getExpiresAt().isAfter(LocalDateTime.now());
    }

    private String normalizeRequired(String value, String message) {
        String normalized = Objects.toString(value, "").trim();
        if (normalized.isEmpty()) {
            throw new BusinessException(message);
        }
        return normalized;
    }
}
