package tech.easyflow.chatlog.service.impl;

import org.springframework.stereotype.Service;
import tech.easyflow.chatlog.config.ChatCacheProperties;
import tech.easyflow.chatlog.domain.dto.ChatMessageRecord;
import tech.easyflow.chatlog.domain.dto.ChatSessionSummary;
import tech.easyflow.chatlog.domain.dto.PublicChatSessionRestoreResult;
import tech.easyflow.chatlog.service.ChatRoundOperateService;
import tech.easyflow.chatlog.service.ChatSessionQueryService;
import tech.easyflow.chatlog.service.PublicChatSessionRestoreService;
import tech.easyflow.common.web.exceptions.BusinessException;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
public class PublicChatSessionRestoreServiceImpl implements PublicChatSessionRestoreService {

    private final ChatSessionQueryService chatSessionQueryService;
    private final ChatRoundOperateService chatRoundOperateService;
    private final ChatCacheProperties chatCacheProperties;

    public PublicChatSessionRestoreServiceImpl(ChatSessionQueryService chatSessionQueryService,
                                               ChatRoundOperateService chatRoundOperateService,
                                               ChatCacheProperties chatCacheProperties) {
        this.chatSessionQueryService = chatSessionQueryService;
        this.chatRoundOperateService = chatRoundOperateService;
        this.chatCacheProperties = chatCacheProperties;
    }

    @Override
    public PublicChatSessionRestoreResult restoreSession(BigInteger userId, BigInteger assistantId, BigInteger sessionId, Integer limit) {
        PublicChatSessionRestoreResult result = new PublicChatSessionRestoreResult();
        result.setConversationId(sessionId == null ? null : sessionId.toString());
        if (userId == null || assistantId == null || sessionId == null) {
            return result;
        }

        ChatSessionSummary summary = chatSessionQueryService.getSessionSummary(sessionId);
        if (summary == null || Integer.valueOf(1).equals(summary.getIsDeleted())) {
            return result;
        }
        if (!Objects.equals(summary.getUserId(), userId)) {
            return result;
        }
        if (!Objects.equals(summary.getAssistantId(), assistantId)) {
            return result;
        }

        List<ChatMessageRecord> tailMessages = new ArrayList<>(chatSessionQueryService.getRecentTail(sessionId, resolveLimit(limit)));
        Collections.reverse(tailMessages);

        result.setSessionExists(true);
        result.setSession(summary);
        result.setMessages(tailMessages);
        return result;
    }

    @Override
    public List<ChatMessageRecord> listVariants(BigInteger userId, BigInteger assistantId, BigInteger sessionId, BigInteger roundId) {
        requireOwnedSession(userId, assistantId, sessionId);
        return chatRoundOperateService.listVariants(sessionId, roundId);
    }

    @Override
    public ChatMessageRecord selectVariant(BigInteger userId, BigInteger assistantId, BigInteger sessionId, BigInteger roundId, Integer variantIndex, BigInteger operatorId) {
        requireOwnedSession(userId, assistantId, sessionId);
        return chatRoundOperateService.selectVariant(sessionId, roundId, variantIndex, operatorId);
    }

    private int resolveLimit(Integer limit) {
        int defaultLimit = Math.max(chatCacheProperties.getTailSize(), 1);
        if (limit == null || limit <= 0) {
            return defaultLimit;
        }
        return Math.min(limit, defaultLimit);
    }

    private ChatSessionSummary requireOwnedSession(BigInteger userId, BigInteger assistantId, BigInteger sessionId) {
        ChatSessionSummary summary = chatSessionQueryService.getSessionSummary(sessionId);
        if (summary == null || Integer.valueOf(1).equals(summary.getIsDeleted())) {
            throw new BusinessException("会话不存在");
        }
        if (!Objects.equals(summary.getUserId(), userId) || !Objects.equals(summary.getAssistantId(), assistantId)) {
            throw new BusinessException("无权访问该会话");
        }
        return summary;
    }
}
