package org.xyzh.ai.controller;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.xyzh.api.ai.chat.AiChatService;
import org.xyzh.api.ai.history.AiChatHistoryService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.api.ai.dto.DifyFileInfo;
import org.xyzh.common.dto.ai.TbAiConversation;
import org.xyzh.common.dto.ai.TbAiMessage;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description AI对话控制器
 * @filename AiChatController.java
 * @author AI Assistant
 * @copyright xyzh
 * @since 2025-11-04
 */
@Slf4j
@RestController
@RequestMapping("/ai/chat")
public class AiChatController {

    @Autowired
    private AiChatService chatService;

    @Autowired
    private AiChatHistoryService chatHistoryService;

    // ===================== 对话相关 =====================

    /**
     * @description 准备流式对话会话（POST接收复杂参数）
     * @param requestBody 请求体（agentId, conversationId, query, files）
     * @return ResultDomain<String> 返回sessionId
     * @author AI Assistant
     * @since 2025-11-06
     */
    @PostMapping("/stream/prepare")
    public ResultDomain<String> prepareStreamChat(@RequestBody Map<String, Object> requestBody) {
        String agentId = (String) requestBody.get("agentId");
        String conversationId = (String) requestBody.get("conversationId");
        String query = (String) requestBody.get("query");
        
        // 转换 files 数据
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> filesRaw = (List<Map<String, Object>>) requestBody.get("files");
        
        List<DifyFileInfo> filesData = null;
        if (filesRaw != null && !filesRaw.isEmpty()) {
            filesData = filesRaw.stream()
                    .map(fileMap -> {
                        // 使用Fastjson2转换Map为对象
                        String json = JSON.toJSONString(fileMap);
                        return JSON.parseObject(json, DifyFileInfo.class);
                    })
                    .collect(Collectors.toList());
        }
        
        log.info("准备流式对话会话: agentId={}, query={}, files={}", 
                agentId, query, filesData != null ? filesData.size() : 0);

        return chatService.prepareChatSession(agentId, conversationId, query, filesData);
    }

    /**
     * @description 流式对话（SSE）- GET建立SSE连接
     * @param sessionId 会话标识
     * @return SseEmitter SSE流式推送对象
     * @author AI Assistant
     * @since 2025-11-06
     */
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamChat(@RequestParam(name = "sessionId") String sessionId) {
        log.info("建立SSE连接: sessionId={}", sessionId);
        return chatService.streamChatWithSse(sessionId);
    }

    /**
     * @description 阻塞式对话
     * @param requestBody 请求体（agentId, conversationId, query）
     * @return ResultDomain<TbAiMessage>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/blocking")
    public ResultDomain<TbAiMessage> blockingChat(@RequestBody Map<String, Object> requestBody) {
        String agentId = (String) requestBody.get("agentId");
        String conversationId = (String) requestBody.get("conversationId");
        String query = (String) requestBody.get("query");
        log.info("阻塞式对话: agentId={}, conversationId={}, query={}", agentId, conversationId, query);
        return chatService.blockingChat(agentId, conversationId, query);
    }

    
    /**
     * @description 停止对话生成（通过Dify TaskID）
     * @param requestBody 请求体（taskId, agentId）
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-05
     */
    @PostMapping("/stop-by-taskid")
    public ResultDomain<Boolean> stopChatByTaskId(@RequestBody Map<String, Object> requestBody) {
        String taskId = (String) requestBody.get("taskId");
        String agentId = (String) requestBody.get("agentId");
        log.info("停止对话生成(通过TaskID): taskId={}, agentId={}", taskId, agentId);
        return chatService.stopChatByTaskId(taskId, agentId);
    }

    /**
     * @description 重新生成回答（SSE流式）
     * @param messageId 原消息ID
     * @return SseEmitter SSE流式推送对象
     * @author AI Assistant
     * @since 2025-11-05
     */
    @GetMapping(value = "/regenerate/{messageId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter regenerateAnswer(@PathVariable(name = "messageId") String messageId) {
        log.info("重新生成回答: messageId={}", messageId);
        return chatService.regenerateAnswerWithSse(messageId);
    }

    /**
     * @description 评价消息
     * @param messageId 消息ID
     * @param requestBody 请求体（rating, feedback）
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/message/{messageId}/rate")
    public ResultDomain<Boolean> rateMessage(
            @PathVariable(name = "messageId") String messageId,
            @RequestBody Map<String, Object> requestBody) {
        Integer rating = (Integer) requestBody.get("rating");
        String feedback = (String) requestBody.get("feedback");
        
        log.info("评价消息: messageId={}, rating={}", messageId, rating);
        return chatService.rateMessage(messageId, rating, feedback);
    }

    // ===================== 会话管理 =====================

    /**
     * @description 创建会话
     * @param requestBody 请求体（agentId, title）
     * @return ResultDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/conversation")
    public ResultDomain<TbAiConversation> createConversation(@RequestBody Map<String, Object> requestBody) {
        String agentId = (String) requestBody.get("agentId");
        String title = (String) requestBody.get("title");
        log.info("创建会话: agentId={}, title={}", agentId, title);
        return chatService.createConversation(agentId, title);
    }

    /**
     * @description 获取会话信息
     * @param conversationId 会话ID
     * @return ResultDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/conversation/{conversationId}")
    public ResultDomain<TbAiConversation> getConversation(@PathVariable(name = "conversationId") String conversationId) {
        log.info("获取会话信息: conversationId={}", conversationId);
        return chatService.getConversation(conversationId);
    }

    /**
     * @description 更新会话
     * @param conversation 会话信息
     * @return ResultDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PutMapping("/conversation")
    public ResultDomain<TbAiConversation> updateConversation(@RequestBody TbAiConversation conversation) {
        log.info("更新会话: id={}", conversation.getID());
        return chatService.updateConversation(conversation);
    }

    /**
     * @description 删除会话
     * @param conversationId 会话ID
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @DeleteMapping("/conversation/{conversationId}")
    public ResultDomain<Boolean> deleteConversation(@PathVariable(name = "conversationId") String conversationId) {
        log.info("删除会话: conversationId={}", conversationId);
        return chatService.deleteConversation(conversationId);
    }

    /**
     * @description 获取用户的会话列表
     * @param agentId 智能体ID（可选）
     * @return ResultDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/conversations")
    public ResultDomain<TbAiConversation> listUserConversations(
            @RequestParam(name = "agentId", required = false) String agentId) {
        log.info("获取用户会话列表: agentId={}", agentId);
        return chatService.listUserConversations(agentId);
    }

    // ===================== 消息管理 =====================

    /**
     * @description 获取会话的消息列表
     * @param conversationId 会话ID
     * @return ResultDomain<TbAiMessage>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/conversation/{conversationId}/messages")
    public ResultDomain<TbAiMessage> listMessages(@PathVariable(name = "conversationId") String conversationId) {
        log.info("获取会话消息列表: conversationId={}", conversationId);
        return chatService.listMessages(conversationId);
    }

    /**
     * @description 获取单条消息
     * @param messageId 消息ID
     * @return ResultDomain<TbAiMessage>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/message/{messageId}")
    public ResultDomain<TbAiMessage> getMessage(@PathVariable(name = "messageId") String messageId) {
        log.info("获取消息: messageId={}", messageId);
        return chatService.getMessage(messageId);
    }

    /**
     * @description 生成会话摘要（异步）
     * @param conversationId 会话ID
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/conversation/{conversationId}/summary")
    public ResultDomain<Boolean> generateSummary(@PathVariable(name = "conversationId") String conversationId) {
        log.info("生成会话摘要: conversationId={}", conversationId);
        return chatService.generateSummaryAsync(conversationId);
    }

    // ===================== 历史记录相关 =====================

    /**
     * @description 分页查询会话历史
     * @param requestBody 请求体（agentId, keyword, isFavorite, startDate, endDate, pageParam）
     * @return PageDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/history/conversations/page")
    public PageDomain<TbAiConversation> pageConversationHistory(@RequestBody Map<String, Object> requestBody) {
        String agentId = (String) requestBody.get("agentId");
        String keyword = (String) requestBody.get("keyword");
        Boolean isFavorite = (Boolean) requestBody.get("isFavorite");
        PageParam pageParam = (PageParam) requestBody.get("pageParam");
        
        log.info("分页查询会话历史: agentId={}, keyword={}", agentId, keyword);
        return chatHistoryService.pageUserConversations(agentId, keyword, isFavorite, null, null, pageParam);
    }

    /**
     * @description 搜索会话
     * @param keyword 关键词
     * @param pageParam 分页参数
     * @return PageDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PostMapping("/history/search")
    public PageDomain<TbAiConversation> searchConversations(
            @RequestParam(name = "keyword") String keyword,
            @RequestBody PageParam pageParam) {
        log.info("搜索会话: keyword={}", keyword);
        return chatHistoryService.searchConversations(keyword, pageParam);
    }

    /**
     * @description 收藏/取消收藏会话
     * @param requestBody 请求体（conversationId, isFavorite）
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PutMapping("/history/conversation/favorite")
    public ResultDomain<Boolean> toggleFavorite(@RequestBody Map<String, Object> requestBody) {
        String conversationId = (String) requestBody.get("conversationId");
        Boolean isFavorite = (Boolean) requestBody.get("isFavorite");
        log.info("{}收藏会话: conversationId={}", isFavorite ? "添加" : "取消", conversationId);
        return chatHistoryService.toggleFavorite(conversationId, isFavorite);
    }

    /**
     * @description 置顶/取消置顶会话
     * @param requestBody 请求体（conversationId, isPinned）
     * @return ResultDomain<Boolean>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @PutMapping("/history/conversation/pin")
    public ResultDomain<Boolean> togglePin(@RequestBody Map<String, Object> requestBody) {
        String conversationId = (String) requestBody.get("conversationId");
        Boolean isPinned = (Boolean) requestBody.get("isPinned");
        log.info("{}置顶会话: conversationId={}", isPinned ? "添加" : "取消", conversationId);
        return chatHistoryService.togglePin(conversationId, isPinned);
    }

    /**
     * @description 批量删除会话
     * @param requestBody 请求体（conversationIds）
     * @return ResultDomain<Integer>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @DeleteMapping("/history/conversations/batch")
    public ResultDomain<Integer> batchDeleteConversations(@RequestBody Map<String, Object> requestBody) {
        @SuppressWarnings("unchecked")
        List<String> conversationIds = (List<String>) requestBody.get("conversationIds");
        log.info("批量删除会话: count={}", conversationIds.size());
        return chatHistoryService.batchDeleteConversations(conversationIds);
    }

    /**
     * @description 导出会话（Markdown格式）
     * @param conversationId 会话ID
     * @return ResultDomain<String>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/history/export/markdown/{conversationId}")
    public ResultDomain<String> exportAsMarkdown(@PathVariable(name = "conversationId") String conversationId) {
        log.info("导出会话（Markdown）: conversationId={}", conversationId);
        return chatHistoryService.exportConversationAsMarkdown(conversationId);
    }

    /**
     * @description 导出会话（JSON格式）
     * @param conversationId 会话ID
     * @return ResultDomain<String>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/history/export/json/{conversationId}")
    public ResultDomain<String> exportAsJson(@PathVariable(name = "conversationId") String conversationId) {
        log.info("导出会话（JSON）: conversationId={}", conversationId);
        return chatHistoryService.exportConversationAsJson(conversationId);
    }

    /**
     * @description 获取最近对话列表
     * @param limit 限制数量（可选，默认10）
     * @return ResultDomain<TbAiConversation>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/history/recent")
    public ResultDomain<TbAiConversation> getRecentConversations(
            @RequestParam(name = "limit", defaultValue = "10") Integer limit) {
        log.info("获取最近对话列表: limit={}", limit);
        return chatHistoryService.getRecentConversations(limit);
    }

    /**
     * @description 获取用户对话统计
     * @param userId 用户ID（可选）
     * @return ResultDomain<Map<String, Object>>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/history/statistics")
    public ResultDomain<Map<String, Object>> getUserChatStatistics(
            @RequestParam(name = "userId", required = false) String userId) {
        log.info("获取用户对话统计: userId={}", userId);
        return chatHistoryService.getUserChatStatistics(userId);
    }

    /**
     * @description 获取会话详细统计
     * @param conversationId 会话ID
     * @return ResultDomain<Map<String, Object>>
     * @author AI Assistant
     * @since 2025-11-04
     */
    @GetMapping("/history/conversation/{conversationId}/statistics")
    public ResultDomain<Map<String, Object>> getConversationStatistics(@PathVariable(name = "conversationId") String conversationId) {
        log.info("获取会话统计: conversationId={}", conversationId);
        return chatHistoryService.getConversationStatistics(conversationId);
    }
}
