package org.dromara.talk.controller.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.DictDataDTO;
import org.dromara.common.core.service.DictService;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.talk.domain.bo.TalkAgentBo;
import org.dromara.talk.domain.bo.TalkSessionBo;
import org.dromara.talk.domain.vo.TalkAgentVo;
import org.dromara.talk.service.IChatService;
import org.dromara.talk.service.ITalkAgentService;
import org.dromara.talk.service.ITalkSessionService;
import org.dromara.talk.service.IPhoneUserService;
import org.dromara.talk.domain.bo.PhoneUserBo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

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

/**
 * 对话接口（对话前端）
 *
 * @author Lion Li
 * @date 2026-01-27
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/talk")
@CrossOrigin(origins = "*", maxAge = 3600)
public class ChatController {

    private final IChatService chatService;
    private final DictService dictService;
    private final ITalkAgentService talkAgentService;
    private final ITalkSessionService talkSessionService;
    private final IPhoneUserService phoneUserService;

    /**
     * 获取TTS发言人字典
     * 返回系统支持的TTS发言人列表，用于AI动态选择合适的发言人
     *
     * @return TTS发言人字典列表
     */
    @GetMapping("/dict/ttsVcn")
    public List<DictDataDTO> getTtsVcnDict() {
        return dictService.getDictData("tts_vcn");
    }

    /**
     * 根据当前登录用户ID获取对应的客服
     * 用于对话前端自动匹配客服
     *
     * @return 客服配置，如果没有找到则返回null
     */
    @GetMapping("/agent/my")
    public Map<String, Object> getMyAgent() {
        try {
            Long userId = LoginHelper.getUserId();
            TalkAgentVo agent = talkAgentService.queryByUserId(userId);
            if (agent != null) {
                return Map.of("code", 200, "data", agent);
            } else {
                return Map.of("code", 404, "msg", "未找到对应的客服");
            }
        } catch (Exception e) {
            log.error("获取当前用户客服失败", e);
            return Map.of("code", 500, "msg", "获取客服失败: " + e.getMessage());
        }
    }

    /**
     * 更新客服配置
     * 用于对话前端在开始对话时更新客服的TTS配置和状态
     *
     * @param id 客服ID
     * @param bo 客服配置参数，包含：
     *           - ttsSpeed: TTS语速
     *           - ttsPitch: TTS音调
     *           - ttsVolume: TTS音量
     *           - ttsBgs: TTS背景音开关
     *           - status: 客服状态（2=对话中）
     * @return 更新结果
     */
    @PutMapping("/agent/{id}")
    public Map<String, Object> updateAgentConfig(@PathVariable Long id, @RequestBody TalkAgentBo bo) {
        bo.setId(id);
        boolean success = talkAgentService.updateByBo(bo);
        return Map.of("success", success);
    }

    /**
     * 开始对话（通用接口）
     * 支持普通对话和RPA对话场景
     *
     * @param id 客服ID
     * @param request 可选参数，包含customerPhone（RPA场景使用）
     * @return 开始对话结果，包含sessionId
     */
    @PostMapping("/agent/{id}/start")
    public Map<String, Object> startChat(@PathVariable Long id, @RequestBody(required = false) Map<String, String> request) {
        boolean success = talkAgentService.changeAgentStatus(id, "2");
        if (success) {
            Long userId = 0L;
            try {
                userId = LoginHelper.getUserId();
            } catch (Exception e) {
                log.warn("获取登录用户ID失败，使用默认值", e);
            }

            String tempSessionId = UUID.randomUUID().toString();
            String customerPhone = request != null ? request.get("customerPhone") : null;

            // 如果有客户电话，检查并保存到 phone_user 表
            if (customerPhone != null && !customerPhone.isEmpty()) {
                try {
                    PhoneUserBo phoneUserBo = new PhoneUserBo();
                    phoneUserBo.setCustomerPhone(customerPhone);
                    phoneUserService.insertByBo(phoneUserBo);
                    log.info("新客户电话已保存: {}", customerPhone);
                } catch (Exception e) {
                    // 如果插入失败（可能是重复），忽略错误继续执行
                    log.debug("客户电话可能已存在: {}", customerPhone);
                }
            }

            TalkSessionBo sessionBo = new TalkSessionBo();
            sessionBo.setSessionId(tempSessionId);
            sessionBo.setAgentId(id);
            sessionBo.setStartTime(new Date());
            sessionBo.setUserId(userId);
            if (customerPhone != null) {
                sessionBo.setCustomerPhone(customerPhone);
            }
            talkSessionService.insertByBo(sessionBo);

            log.info("客服 {} 开始对话，sessionId: {}, customerPhone: {}, 创建人: {}", id, tempSessionId, customerPhone, userId);
            return Map.of("success", true, "code", 200, "sessionId", tempSessionId);
        } else {
            log.warn("客服 {} 开始对话失败，可能已被占用", id);
            return Map.of("success", false, "code", 400, "msg", "该客服已被其他用户占用，请选择其他客服");
        }
    }

    /**
     * 挂断电话
     * 用户挂断电话后，更新会话结束时间并将客服状态改回0（正常）
     *
     * @param id      客服ID
     * @param request 包含sessionId与chatHistory数组的请求体
     * @return 更新结果
     */
    @PostMapping("/agent/{id}/hangup")
    public Map<String, Object> hangupCall(@PathVariable Long id, @RequestBody Map<String, Object> request) {
        String sessionId = (String) request.get("sessionId");
        List<Map<String, Object>> chatHistory = (List<Map<String, Object>>) request.get("chatHistory");

        // 更新会话结束时间并保存对话内容
        if (sessionId != null) {
            talkSessionService.updateEndTime(sessionId);

            // 保存对话内容
            if (chatHistory != null && !chatHistory.isEmpty()) {
                try {
                    // 转换前端格式到后端格式
                    List<Map<String, String>> messages = new ArrayList<>();
                    for (Map<String, Object> msg : chatHistory) {
                        Map<String, String> message = new HashMap<>();
                        String type = (String) msg.get("type");
                        String content = (String) msg.get("content");

                        // 转换 type: user/agent 到 role: user/assistant
                        message.put("role", "user".equals(type) ? "user" : "assistant");
                        message.put("content", content);
                        message.put("timestamp", String.valueOf(System.currentTimeMillis()));
                        messages.add(message);
                    }

                    String conversationJson = new ObjectMapper().writeValueAsString(messages);
                    talkSessionService.saveOrUpdateConversation(sessionId, id, conversationJson, null, null);
                    log.info("挂断时保存对话内容，会话ID: {}, 消息数量: {}", sessionId, messages.size());
                } catch (Exception e) {
                    log.error("保存对话内容失败", e);
                }
            }
        }

        // 将客服状态改为空闲
        TalkAgentBo bo = new TalkAgentBo();
        bo.setId(id);
        bo.setStatus("0");
        boolean success = talkAgentService.updateByBo(bo);
        log.info("客服 {} 挂断电话，状态已改为空闲中，会话ID: {}", id, sessionId);
        return Map.of("success", success);
    }

    /**
     * 流式处理用户消息
     * 使用SSE实时推送文本和音频数据
     *
     * @param request 请求参数，包含：
     *                - message: 用户消息内容
     *                - agentId: 客服ID
     *                - agentGender: 客服性别（不需要用户传递前端做处理）
     *                - ttsVcnList: TTS发音人列表 （不需要用户传递前端做处理）
     *                - conversationId: 会话ID
     *                - isGreeting: 是否为欢迎语
     *                - requestId: 请求ID
     */
    @PostMapping("/message/stream")
    public SseEmitter handleMessageStream(@RequestBody Map<String, Object> request) {
        String userMessage = (String) request.get("message");
        Long agentId = request.get("agentId") != null ? Long.valueOf(request.get("agentId").toString()) : null;
        String agentGender = (String) request.get("agentGender");
        List<Map<String, String>> ttsVcnList = (List<Map<String, String>>) request.get("ttsVcnList");
        String conversationId = (String) request.get("conversationId");
        Boolean isGreeting = request.get("isGreeting") != null ? Boolean.valueOf(request.get("isGreeting").toString()) : false;
        Integer requestId = request.get("requestId") != null ? Integer.valueOf(request.get("requestId").toString()) : null;

        log.info("收到流式消息请求: {}, 客服ID: {}, 对话ID: {}, 请求ID: {}", userMessage, agentId, conversationId, requestId);

        SseEmitter emitter = new SseEmitter(60000L);
        chatService.processMessageStream(userMessage, agentId, agentGender, ttsVcnList, conversationId, isGreeting, requestId, emitter);
        return emitter;
    }

}
