package com.ycwl.basic.service.mobile.impl;

import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.integration.glm.GlmClient;
import com.ycwl.basic.mapper.FaceChatConversationMapper;
import com.ycwl.basic.mapper.FaceChatMessageMapper;
import com.ycwl.basic.model.mobile.chat.*;
import com.ycwl.basic.model.mobile.chat.entity.FaceChatConversationEntity;
import com.ycwl.basic.model.mobile.chat.entity.FaceChatMessageEntity;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.service.mobile.FaceChatService;
import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ai.z.openapi.service.model.ChatMessage;
import ai.z.openapi.service.model.ChatMessageRole;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class FaceChatServiceImpl implements FaceChatService {

    private static final String STATUS_ACTIVE = "active";
    private static final String STATUS_CLOSED = "closed";
    private static final String ROLE_USER = "user";
    private static final String ROLE_ASSISTANT = "assistant";
    private static final String DEFAULT_MODEL = "glm-4.5-airx";
    private static final int HISTORY_LIMIT = 50;

    private final FaceChatConversationMapper conversationMapper;
    private final FaceChatMessageMapper messageMapper;
    private final FaceRepository faceRepository;
    @Lazy
    private final GlmClient glmClient;

    @Override
    public ChatConversationVO getOrCreateConversation(Long faceId, Long memberId) {
        FaceChatConversationEntity exist = conversationMapper.findByFaceId(faceId);
        if (exist != null) {
            assertOwner(exist, memberId);
            return toConversationVO(exist);
        }
        // DEBUG阶段，暂时不检查
//        FaceEntity face = faceRepository.getFace(faceId);
//        if (face == null) {
//            throw new BaseException("人脸不存在");
//        }
//        if (!Objects.equals(face.getMemberId(), memberId)) {
//            throw new BaseException("无权访问该人脸");
//        }
        FaceChatConversationEntity entity = new FaceChatConversationEntity();
        entity.setId(SnowFlakeUtil.getLongId());
        entity.setFaceId(faceId);
        entity.setMemberId(memberId);
        entity.setStatus(STATUS_ACTIVE);
        entity.setModel(DEFAULT_MODEL);
        conversationMapper.insert(entity);
        return toConversationVO(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatSendMessageResp sendMessage(Long conversationId, Long memberId, String content, String traceId) {
        ChatSendMessageStreamResp result = doSend(conversationId, memberId, content, traceId, null);
        ChatSendMessageResp resp = new ChatSendMessageResp();
        resp.setUserMessage(result.getUserMessage());
        resp.setAssistantMessage(result.getAssistantMessage());
        resp.setTraceId(result.getTraceId());
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatSendMessageStreamResp sendMessageStream(Long conversationId, Long memberId, String content, String traceId,
                                                       java.util.function.Consumer<String> chunkConsumer) {
        return doSend(conversationId, memberId, content, traceId, chunkConsumer);
    }

    @Override
    public ChatMessagePageResp listMessages(Long conversationId, Integer cursor, Integer limit, Long memberId) {
        FaceChatConversationEntity conv = conversationMapper.getById(conversationId);
        if (conv == null) {
            throw new BaseException("会话不存在");
        }
        assertOwner(conv, memberId);
        int pageSize = limit == null ? 50 : Math.max(1, Math.min(limit, 100));
        List<FaceChatMessageEntity> list = messageMapper.listByConversation(conversationId, cursor, pageSize);
        List<ChatMessageVO> vos = list.stream().map(this::toMessageVO).collect(Collectors.toList());
        ChatMessagePageResp resp = new ChatMessagePageResp();
        resp.setMessages(vos);
        if (!list.isEmpty()) {
            resp.setNextCursor(list.getLast().getSeq());
        } else {
            resp.setNextCursor(cursor == null ? 0 : cursor);
        }
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeConversation(Long conversationId, Long memberId) {
        FaceChatConversationEntity conv = conversationMapper.getById(conversationId);
        if (conv == null) {
            throw new BaseException("会话不存在");
        }
        assertOwner(conv, memberId);
        if (STATUS_CLOSED.equals(conv.getStatus())) {
            return;
        }
        conversationMapper.updateStatus(conversationId, STATUS_CLOSED);
    }

    private ChatSendMessageStreamResp doSend(Long conversationId, Long memberId, String content, String traceId,
                                             java.util.function.Consumer<String> liveConsumer) {
        if (StringUtils.isBlank(content)) {
            throw new BaseException("消息内容不能为空");
        }
        FaceChatConversationEntity conv = conversationMapper.getById(conversationId);
        if (conv == null) {
            throw new BaseException("会话不存在");
        }
        assertOwner(conv, memberId);
        if (STATUS_CLOSED.equals(conv.getStatus())) {
            throw new BaseException("会话已关闭，请重新创建");
        }
        String resolvedTraceId = StringUtils.isBlank(traceId) ? UUID.randomUUID().toString() : traceId;

        Integer maxSeq = messageMapper.maxSeqForUpdate(conversationId);
        int baseSeq = maxSeq == null ? 0 : maxSeq;
        int userSeq = baseSeq + 1;

        FaceChatMessageEntity userMsg = buildMessage(conv, userSeq, ROLE_USER, content, resolvedTraceId, null);
        messageMapper.insert(userMsg);

        long start = System.currentTimeMillis();
        List<FaceChatMessageEntity> recentDesc = messageMapper.listRecentByConversation(conversationId, HISTORY_LIMIT);
        Collections.reverse(recentDesc); // 按时间升序
        List<ChatMessage> chatMessages = recentDesc.stream()
                .map(this::toChatMessage)
                .collect(Collectors.toList());

        CopyOnWriteArrayList<String> chunks = new CopyOnWriteArrayList<>();
        java.util.function.Consumer<String> chunkConsumer = piece -> {
            if (StringUtils.isNotBlank(piece)) {
                chunks.add(piece);
                if (liveConsumer != null) {
                    liveConsumer.accept(piece);
                }
            }
        };

        String assistantText = glmClient.streamReply(conv.getFaceId(), memberId, resolvedTraceId, chatMessages, chunkConsumer);
        if (StringUtils.isBlank(assistantText)) {
            assistantText = "GLM 暂未接入，稍后再试。";
            chunkConsumer.accept(assistantText);
        }
        int latency = (int) (System.currentTimeMillis() - start);

        FaceChatMessageEntity assistantMsg = buildMessage(conv, userSeq + 1, ROLE_ASSISTANT, assistantText, resolvedTraceId, latency);
        messageMapper.insert(assistantMsg);

        ChatSendMessageStreamResp resp = new ChatSendMessageStreamResp();
        resp.setUserMessage(toMessageVO(userMsg));
        resp.setAssistantMessage(toMessageVO(assistantMsg));
        resp.setTraceId(resolvedTraceId);
        resp.setChunks(chunks);
        return resp;
    }

    private FaceChatMessageEntity buildMessage(FaceChatConversationEntity conv, int seq, String role, String content, String traceId, Integer latencyMs) {
        FaceChatMessageEntity msg = new FaceChatMessageEntity();
        msg.setId(SnowFlakeUtil.getLongId());
        msg.setConversationId(conv.getId());
        msg.setFaceId(conv.getFaceId());
        msg.setSeq(seq);
        msg.setRole(role);
        msg.setContent(content);
        msg.setTraceId(traceId);
        msg.setLatencyMs(latencyMs);
        msg.setCreatedAt(new Date());
        return msg;
    }

    private void assertOwner(FaceChatConversationEntity conv, Long memberId) {
        if (!Objects.equals(conv.getMemberId(), memberId)) {
            throw new BaseException("无权访问该会话");
        }
    }

    private ChatConversationVO toConversationVO(FaceChatConversationEntity entity) {
        ChatConversationVO vo = new ChatConversationVO();
        vo.setConversationId(entity.getId());
        vo.setFaceId(entity.getFaceId());
        vo.setStatus(entity.getStatus());
        vo.setModel(entity.getModel());
        return vo;
    }

    private ChatMessageVO toMessageVO(FaceChatMessageEntity entity) {
        ChatMessageVO vo = new ChatMessageVO();
        vo.setId(entity.getId());
        vo.setSeq(entity.getSeq());
        vo.setRole(entity.getRole());
        vo.setContent(entity.getContent());
        vo.setTraceId(entity.getTraceId());
        vo.setCreatedAt(entity.getCreatedAt());
        return vo;
    }

    private ChatMessage toChatMessage(FaceChatMessageEntity entity) {
        String role = entity.getRole();
        String mappedRole = ChatMessageRole.USER.value();
        if (ROLE_ASSISTANT.equalsIgnoreCase(role)) {
            mappedRole = ChatMessageRole.ASSISTANT.value();
        } else if ("system".equalsIgnoreCase(role)) {
            mappedRole = ChatMessageRole.SYSTEM.value();
        }
        return ChatMessage.builder()
                .role(mappedRole)
                .content(entity.getContent())
                .build();
    }
}
