package com.infoepoch.pms.agent.platform.chatbot.application;

import com.infoepoch.pms.agent.platform.agent.application.AgentQueryService;
import com.infoepoch.pms.agent.platform.agent.domain.Agent;
import com.infoepoch.pms.agent.platform.chatbot.application.dto.ChatbotDetailResponse;
import com.infoepoch.pms.agent.platform.chatbot.application.dto.ChatbotSummaryResponse;
import com.infoepoch.pms.agent.platform.chatbot.application.dto.CreateChatbotRequest;
import com.infoepoch.pms.agent.platform.chatbot.application.dto.UpdateChatbotRequest;
import com.infoepoch.pms.agent.platform.chatbot.domain.Chatbot;
import com.infoepoch.pms.agent.platform.chatbot.domain.ChatbotAgents;
import com.infoepoch.pms.agent.platform.chatbot.domain.irepository.IChatbotAgentsRepository;
import com.infoepoch.pms.agent.platform.chatbot.domain.irepository.IChatbotRepository;
import com.infoepoch.pms.agent.platform.model.application.ModelQueryService;
import com.infoepoch.pms.agent.platform.model.domain.AiModelConfig;
import com.infoepoch.pms.agent.platform.shared.exception.BusinessException;
import com.infoepoch.pms.agent.platform.shared.response.ResultCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * 聊天机器人管理服务。
 */
@Service
@RequiredArgsConstructor
public class ChatbotService {

    private final IChatbotRepository chatbotRepository;
    private final IChatbotAgentsRepository chatbotAgentsRepository;
    private final ModelQueryService modelQueryService;
    private final AgentQueryService agentQueryService;
    private final ChatbotQueryService chatbotQueryService;
    private final ChatbotToolQueryService chatbotToolQueryService;

    /**
     * 创建聊天机器人。
     *
     * @param req 创建请求 DTO
     * @return 聊天机器人摘要响应
     */
    @Transactional
    public ChatbotSummaryResponse create(CreateChatbotRequest req) {
        if (chatbotRepository.existsByTrimmedName(req.getName())) {
            throw new BusinessException(ResultCode.RESOURCE_ALREADY_EXISTS,
                    "聊天机器人名称 [" + req.getName() + "] 已存在");
        }
        validateEnabledTools(req.getEnabledTools());
        AiModelConfig modelConfig = resolveModelConfig(req.getModelConfigId());
        Set<Agent> subAgents = resolveSubAgents(req.getSubAgentIds());
        Chatbot chatbot = new Chatbot(req.getName(), req.getDescription(), req.getSystemPrompt(),
                modelConfig, req.getEnabledTools(), req.getContextWindowSize(), subAgents);
        persistSubAgents(chatbotRepository.save(chatbot), subAgents);
        return new ChatbotSummaryResponse(chatbotQueryService.findDetailById(chatbot.getId()).orElse(chatbot));
    }

    /**
     * 按 ID 查询聊天机器人详情。
     *
     * @param id 聊天机器人主键
     * @return 聊天机器人详情响应
     */
    @Transactional(readOnly = true)
    public ChatbotDetailResponse findById(String id) {
        return new ChatbotDetailResponse(getChatbotOrThrow(id));
    }

    /**
     * 查询所有聊天机器人。
     *
     * @return 聊天机器人摘要响应列表
     */
    @Transactional(readOnly = true)
    public List<ChatbotSummaryResponse> listAll() {
        return chatbotQueryService.listDetails().stream()
                .map(ChatbotSummaryResponse::new)
                .toList();
    }

    /**
     * 更新聊天机器人配置。
     *
     * @param id 聊天机器人主键
     * @param req 更新请求 DTO
     * @return 更新后的聊天机器人摘要响应
     */
    @Transactional
    public ChatbotSummaryResponse update(String id, UpdateChatbotRequest req) {
        Chatbot chatbot = getChatbotOrThrow(id);
        if (chatbotRepository.existsByTrimmedNameAndIdNot(req.getName(), id)) {
            throw new BusinessException(ResultCode.RESOURCE_ALREADY_EXISTS,
                    "聊天机器人名称 [" + req.getName() + "] 已存在");
        }
        validateEnabledTools(req.getEnabledTools());
        AiModelConfig modelConfig = resolveModelConfig(req.getModelConfigId());
        Set<Agent> subAgents = resolveSubAgents(req.getSubAgentIds());
        chatbot.modify(req.getName(), req.getDescription(), req.getSystemPrompt(), modelConfig,
                req.getEnabledTools(), req.getContextWindowSize(), subAgents);
        persistSubAgents(chatbotRepository.save(chatbot), subAgents);
        return new ChatbotSummaryResponse(getChatbotOrThrow(id));
    }

    /**
     * 删除聊天机器人。
     *
     * @param id 聊天机器人主键
     */
    @Transactional
    public void delete(String id) {
        chatbotAgentsRepository.deleteByChatBotId(id);
        chatbotRepository.delete(getChatbotOrThrow(id).getId());
    }

    /**
     * 切换聊天机器人启用状态。
     *
     * @param id 聊天机器人主键
     * @return 更新后的聊天机器人摘要响应
     */
    @Transactional
    public ChatbotSummaryResponse toggle(String id) {
        Chatbot chatbot = getChatbotOrThrow(id);
        chatbot.toggleEnabled();
        chatbotRepository.save(chatbot);
        return new ChatbotSummaryResponse(getChatbotOrThrow(id));
    }

    /**
     * 按 ID 查询聊天机器人，不存在时抛出业务异常。
     *
     * @param id 聊天机器人 ID
     * @return 聊天机器人实体
     */
    private Chatbot getChatbotOrThrow(String id) {
        return chatbotQueryService.findDetailById(id)
                .orElseThrow(() -> new BusinessException(ResultCode.CHATBOT_NOT_FOUND,
                        "聊天机器人 ID=" + id + " 不存在"));
    }

    /**
     * 解析模型配置。
     *
     * @param modelConfigId 模型配置 ID
     * @return 模型配置，传 null 时返回 null
     */
    private AiModelConfig resolveModelConfig(String modelConfigId) {
        AiModelConfig config = modelQueryService.getModelConfigOrNull(modelConfigId);
        if (config != null && !"LLM".equals(config.getModelType())) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "聊天机器人仅支持引用 LLM 类型模型配置");
        }
        return config;
    }

    /**
     * 解析并去重子智能体集合。
     *
     * @param subAgentIds 子智能体 ID 列表
     * @return 已启用子智能体集合
     */
    private Set<Agent> resolveSubAgents(List<String> subAgentIds) {
        if (subAgentIds == null || subAgentIds.isEmpty()) {
            return new LinkedHashSet<>();
        }
        return new LinkedHashSet<>(agentQueryService.findEnabledByIds(new LinkedHashSet<>(subAgentIds)));
    }

    private void persistSubAgents(Chatbot chatbot, Set<Agent> subAgents) {
        chatbotAgentsRepository.deleteByChatBotId(chatbot.getId());
        List<ChatbotAgents> relations = new ArrayList<>();
        for (Agent subAgent : subAgents) {
            relations.add(new ChatbotAgents(chatbot.getId(), subAgent.getId()));
        }
        relations.forEach(chatbotAgentsRepository::insert);
    }

    /**
     * 校验启用工具是否全部为可配置工具。
     *
     * @param enabledTools 启用工具列表
     */
    private void validateEnabledTools(List<String> enabledTools) {
        if (enabledTools == null) {
            return;
        }
        for (String enabledTool : enabledTools) {
            if (!chatbotToolQueryService.isConfigurableTool(enabledTool)) {
                String toolKey = enabledTool == null ? null : enabledTool.trim();
                throw new BusinessException(ResultCode.PARAM_ERROR,
                        "启用工具标识 [" + toolKey + "] 不存在或不允许配置");
            }
        }
    }

}
