package com.erp.ai.service;

import com.erp.ai.mapper.AiAgentConversationMapper;
import com.erp.ai.mapper.AiAgentMessageMapper;
import com.erp.ai.model.AiAgentConversation;
import com.erp.ai.model.AiAgentMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * AI 대화 모니터링 서비스.
 * vexplor aiAgentConversationService.ts 1:1 포팅.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiAgentConversationService {

    private final AiAgentConversationMapper conversationMapper;
    private final AiAgentMessageMapper messageMapper;

    @Qualifier("aiObjectMapper")
    private final ObjectMapper objectMapper;

    public Map<String, Object> list(int page, int limit, Long agentId) {
        int offset = (page - 1) * limit;
        List<AiAgentConversation> conversations = conversationMapper.list(agentId, limit, offset);
        int total = conversationMapper.count(agentId);
        Map<String, Object> result = new HashMap<>();
        result.put("conversations", conversations.stream().map(this::convToResponseMap).toList());
        result.put("total", total);
        return result;
    }

    public Map<String, Object> getById(long id) {
        AiAgentConversation conv = conversationMapper.getById(id);
        List<AiAgentMessage> messages = conv != null
                ? messageMapper.listByConversationId(id)
                : List.of();
        Map<String, Object> result = new HashMap<>();
        result.put("conversation", conv != null ? convToResponseMap(conv) : null);
        result.put("messages", messages.stream().map(this::messageToResponseMap).toList());
        return result;
    }

    private Map<String, Object> convToResponseMap(AiAgentConversation c) {
        Map<String, Object> row = new HashMap<>();
        row.put("id", c.getId());
        row.put("conversation_id", c.getConversation_id());
        row.put("agent_id", c.getAgent_id());
        row.put("user_id", c.getUser_id());
        row.put("api_key_id", c.getApi_key_id());
        row.put("title", c.getTitle());
        row.put("message_count", c.getMessage_count());
        row.put("total_tokens", c.getTotal_tokens());
        row.put("status", c.getStatus());
        row.put("metadata", c.getMetadata());
        row.put("created_at", c.getCreated_at());
        row.put("updated_at", c.getUpdated_at());
        row.put("agent_name", c.getAgent_name());
        row.put("display_name", c.getDisplay_name());
        parseJsonField(row, "metadata");
        return row;
    }

    private Map<String, Object> messageToResponseMap(AiAgentMessage m) {
        Map<String, Object> row = new HashMap<>();
        row.put("id", m.getId());
        row.put("conversation_id", m.getConversation_id());
        row.put("role", m.getRole());
        row.put("content", m.getContent());
        row.put("tool_calls", m.getTool_calls());
        row.put("token_count", m.getToken_count());
        row.put("metadata", m.getMetadata());
        row.put("created_at", m.getCreated_at());
        parseJsonField(row, "tool_calls");
        parseJsonField(row, "metadata");
        return row;
    }

    private void parseJsonField(Map<String, Object> row, String key) {
        Object val = row.get(key);
        if (val instanceof String s && !s.isBlank()) {
            try {
                row.put(key, objectMapper.readValue(s, Object.class));
            } catch (Exception e) {
                log.warn("Failed to parse JSONB field '{}': {}", key, e.getMessage());
            }
        }
    }

    @Transactional
    public AiAgentConversation createConversation(Long agentId, String userId, Long apiKeyId) {
        AiAgentConversation conv = new AiAgentConversation();
        conv.setConversation_id("conv-" + UUID.randomUUID());
        conv.setAgent_id(agentId);
        conv.setUser_id(userId);
        conv.setApi_key_id(apiKeyId);
        conv.setMetadata("{}");
        conversationMapper.insert(conv);
        return conversationMapper.getById(conv.getId());
    }

    @Transactional
    public void updateMeta(long id, String title, String metadataJson) {
        conversationMapper.updateMeta(id, title, metadataJson);
    }

    @Transactional
    public AiAgentMessage addMessage(long conversationId, String role, String content,
                                     int tokenCount, String toolCallsJson) {
        AiAgentMessage msg = new AiAgentMessage();
        msg.setConversation_id(conversationId);
        msg.setRole(role);
        msg.setContent(content);
        msg.setToken_count(tokenCount);
        msg.setTool_calls(toolCallsJson);
        messageMapper.insert(msg);
        conversationMapper.incrementStats(conversationId, tokenCount);
        return msg;
    }

    @Transactional
    public AiAgentMessage addMessageWithMetadata(long conversationId, String role, String content,
                                                 int tokenCount, String metadataJson) {
        AiAgentMessage msg = new AiAgentMessage();
        msg.setConversation_id(conversationId);
        msg.setRole(role);
        msg.setContent(content);
        msg.setToken_count(tokenCount);
        msg.setMetadata(metadataJson);
        messageMapper.insert(msg);
        conversationMapper.incrementStats(conversationId, tokenCount);
        return msg;
    }

    @Transactional
    public void delete(long id) {
        conversationMapper.delete(id);
    }
}
