package com.huimv.employment.service.conversation;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huimv.employment.dao.entity.FeConversationMessage;
import com.huimv.employment.dao.mapper.FeConversationMessageMapper;
import com.huimv.employment.service.conversation.dto.ConversationMessagePageResponse;
import com.huimv.employment.service.conversation.dto.ConversationMessageResponse;
import com.huimv.employment.service.conversation.dto.ParsedAssistantReply;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.stream.Collectors;

/**
 * AI 对话消息落库与查询。
 */
@Service
public class ConversationMessageService {

    private static final String ROLE_USER = "user";
    private static final String ROLE_ASSISTANT = "assistant";

    private static final int MIN_PAGE = 1;
    private static final int MIN_SIZE = 1;
    private static final int MAX_SIZE = 200;
    private static final int DEFAULT_SIZE = 50;

    private final ConversationService conversationService;
    private final FeConversationMessageMapper feConversationMessageMapper;

    public ConversationMessageService(ConversationService conversationService,
                                      FeConversationMessageMapper feConversationMessageMapper) {
        this.conversationService = conversationService;
        this.feConversationMessageMapper = feConversationMessageMapper;
    }

    /**
     * 分页查询指定会话下的消息，按时间正序。
     */
    public ConversationMessagePageResponse listByConversation(Long userId, Long conversationId, Integer page, Integer size) {
        conversationService.requireOwned(userId, conversationId);
        int resolvedPage = page == null || page < MIN_PAGE ? MIN_PAGE : page;
        int resolvedSize = size == null || size < MIN_SIZE ? DEFAULT_SIZE : Math.min(size, MAX_SIZE);

        Page<FeConversationMessage> pageParam = new Page<>(resolvedPage, resolvedSize);
        LambdaQueryWrapper<FeConversationMessage> wrapper = new LambdaQueryWrapper<FeConversationMessage>()
                .eq(FeConversationMessage::getConversationId, conversationId)
                .orderByAsc(FeConversationMessage::getCreateTime)
                .orderByAsc(FeConversationMessage::getId);
        Page<FeConversationMessage> result = feConversationMessageMapper.selectPage(pageParam, wrapper);

        ConversationMessagePageResponse response = new ConversationMessagePageResponse();
        response.setItems(result.getRecords().stream().map(this::toResponse).collect(Collectors.toList()));
        response.setTotal(result.getTotal());
        response.setPage(resolvedPage);
        response.setSize(resolvedSize);
        response.setHasMore((long) resolvedPage * resolvedSize < result.getTotal());
        return response;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveUserMessage(Long conversationId, String userText) {
        saveUserMessage(conversationId, userText, true);
    }

    /**
     * @param refreshTitle 为 false 时仅刷新 last_message_at，标题由意图分类异步写入
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveUserMessage(Long conversationId, String userText, boolean refreshTitle) {
        if (conversationId == null || !StringUtils.hasText(userText)) {
            return;
        }
        insertMessage(conversationId, ROLE_USER, userText.trim(),
                MessageCardConstants.CONTENT_TYPE_TEXT, null, null, null);
        conversationService.refreshAfterMessage(conversationId, refreshTitle ? userText : null);
    }

    /** 当前会话是否尚无 user 消息（用于首条消息意图分类） */
    public boolean isFirstUserMessage(Long conversationId) {
        if (conversationId == null) {
            return false;
        }
        Long count = feConversationMessageMapper.selectCount(new LambdaQueryWrapper<FeConversationMessage>()
                .eq(FeConversationMessage::getConversationId, conversationId)
                .eq(FeConversationMessage::getRole, ROLE_USER));
        return count == null || count == 0L;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveAssistantMessage(Long conversationId, String assistantText) {
        saveAssistantMessage(conversationId, ParsedAssistantReply.textOnly(
                assistantText != null ? assistantText.trim() : ""));
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveAssistantMessage(Long conversationId, ParsedAssistantReply parsed) {
        if (conversationId == null || parsed == null) {
            return;
        }
        String content = resolveAssistantContent(parsed);
        if (!StringUtils.hasText(content) && !parsed.hasCard()) {
            return;
        }
        String contentType = parsed.hasCard()
                ? parsed.getContentType()
                : MessageCardConstants.CONTENT_TYPE_TEXT;
        String nextAction = parsed.getNextAction();
        if (parsed.hasCard() && !StringUtils.hasText(nextAction)) {
            nextAction = defaultNextAction(contentType);
        }
        insertMessage(conversationId, ROLE_ASSISTANT, content,
                contentType, parsed.getCardPayload(), nextAction, parsed.getRelatedDraftId());
        conversationService.refreshAfterMessage(conversationId, null);
    }

    private static String resolveAssistantContent(ParsedAssistantReply parsed) {
        if (StringUtils.hasText(parsed.getDisplayText())) {
            return parsed.getDisplayText().trim();
        }
        if (parsed.hasCard()) {
            if (MessageCardConstants.CONTENT_TYPE_CARD_DRAFT.equals(parsed.getContentType())) {
                return "用工草稿已生成，请查看并确认。";
            }
            if (MessageCardConstants.CONTENT_TYPE_CARD_COST.equals(parsed.getContentType())) {
                return "成本测算完成，请选择方案。";
            }
            if (MessageCardConstants.CONTENT_TYPE_CARD_ORDER.equals(parsed.getContentType())) {
                return "方案已确认，请让临时工扫码登记。";
            }
            return "请查看卡片详情。";
        }
        return "";
    }

    private static String defaultNextAction(String contentType) {
        if (MessageCardConstants.CONTENT_TYPE_CARD_DRAFT.equals(contentType)) {
            return MessageCardConstants.NEXT_ACTION_SHOW_EMPLOYMENT_DRAFT;
        }
        if (MessageCardConstants.CONTENT_TYPE_CARD_COST.equals(contentType)) {
            return MessageCardConstants.NEXT_ACTION_OPEN_COST_COMPARISON;
        }
        if (MessageCardConstants.CONTENT_TYPE_CARD_ORDER.equals(contentType)) {
            return MessageCardConstants.NEXT_ACTION_SHOW_ORDER_QRCODE;
        }
        return null;
    }

    private void insertMessage(Long conversationId,
                               String role,
                               String content,
                               String contentType,
                               String cardPayload,
                               String nextAction,
                               Long relatedDraftId) {
        FeConversationMessage message = new FeConversationMessage();
        message.setConversationId(conversationId);
        message.setRole(role);
        message.setContent(content);
        message.setContentType(StringUtils.hasText(contentType)
                ? contentType
                : MessageCardConstants.CONTENT_TYPE_TEXT);
        message.setCardPayload(cardPayload);
        message.setNextAction(nextAction);
        message.setRelatedDraftId(relatedDraftId);
        message.setCreateTime(LocalDateTime.now());
        feConversationMessageMapper.insert(message);
    }

    private ConversationMessageResponse toResponse(FeConversationMessage entity) {
        ConversationMessageResponse response = new ConversationMessageResponse();
        response.setId(entity.getId());
        response.setRole(entity.getRole());
        response.setContent(entity.getContent());
        response.setContentType(entity.getContentType());
        response.setCardPayload(entity.getCardPayload());
        response.setNextAction(entity.getNextAction());
        response.setRelatedDraftId(entity.getRelatedDraftId());
        response.setCreateTime(entity.getCreateTime());
        return response;
    }
}
