package com.infoepoch.pms.agent.domain.itworkbench;

import com.fasterxml.jackson.databind.JsonNode;
import com.infoepoch.pms.agent.common.utils.LogHelper;
import com.infoepoch.pms.agent.config.JsonUtils;
import com.infoepoch.pms.agent.domain.care.log.CareTraceLogSupport;
import com.infoepoch.pms.agent.domain.itworkbench.enums.WorkbenchIntent;
import com.infoepoch.pms.agent.domain.itworkbench.model.QueryDto;
import com.infoepoch.pms.agent.domain.itworkbench.model.WorkbenchConversationState;
import com.infoepoch.pms.agent.domain.itworkbench.model.department.DepartmentWorkDto;
import com.infoepoch.pms.agent.domain.itworkbench.model.kpi.AnnualKpiDto;
import com.infoepoch.pms.agent.domain.itworkbench.model.minutes.DepartmentMinutesDto;
import com.infoepoch.pms.agent.domain.itworkbench.remote.WorkbenchRemoteService;
import com.infoepoch.pms.agent.domain.itworkbench.state.WorkbenchConversationStateService;
import com.infoepoch.pms.agent.domain.itworkbench.understanding.WorkbenchIntentRecognizer;
import com.infoepoch.pms.agent.domain.itworkbench.understanding.WorkbenchQueryUnderstandingService;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;

import java.util.Map;

@Service
public class WorkbenchAIService {

    private final WorkbenchIntentRecognizer intentRecognizer;
    private final WorkbenchQueryUnderstandingService parser;
    private final WorkbenchRemoteService remoteService;
    private final WorkbenchConversationStateService conversationStateService;

    public WorkbenchAIService(
            WorkbenchIntentRecognizer intentRecognizer,
            WorkbenchQueryUnderstandingService parser,
            WorkbenchRemoteService remoteService,
            WorkbenchConversationStateService conversationStateService) {
        this.intentRecognizer = intentRecognizer;
        this.parser = parser;
        this.remoteService = remoteService;
        this.conversationStateService = conversationStateService;
    }

    public Flux<String> streamChat(String traceId, String sessionId, String message) {
        LogHelper.info(this, CareTraceLogSupport.format(
                traceId, sessionId, "workbench_chat_start", "用户消息：" + message
        ));

        // 加载历史状态
        WorkbenchConversationState state = conversationStateService.load(sessionId).orElse(null);

        try {
            // 1. 意图识别
            WorkbenchIntent intent = intentRecognizer.recognize(traceId, sessionId, message, state);
            LogHelper.info(this, CareTraceLogSupport.format(
                    traceId, sessionId, "streamChat", 
                    "消息=[" + message + "] intent=" + intent + " state.lastIntent=" + (state != null ? state.lastIntent() : "null")
            ));

            // 2. 判断是否为全量查询（重置筛选条件）
            boolean isFullDataQuery = isFullDataQuery(message);

            // 3. 判断是否为跨类型切换（新业务类型）
            boolean isCrossTypeSwitch = state != null && state.lastIntent() != null && !state.lastIntent().equals(intent);

            // 4. 判断是否包含业务类型关键词（重新查库）
            boolean isReQueryWithKeyword = isReQueryWithKeyword(message, intent);
            LogHelper.info(this, CareTraceLogSupport.format(
                    traceId, sessionId, "streamChat", 
                    "isFullDataQuery=" + isFullDataQuery + " isCrossTypeSwitch=" + isCrossTypeSwitch + " isReQueryWithKeyword=" + isReQueryWithKeyword
            ));

            // 5. 多轮对话：同类型且无业务关键词时使用历史数据筛选，否则查库
            if (state != null && !isCrossTypeSwitch && !isFullDataQuery && !isReQueryWithKeyword) {
                WorkbenchConversationState.TypeData typeData = getTypeDataForIntent(state, intent);
                LogHelper.info(this, CareTraceLogSupport.format(
                        traceId, sessionId, "streamChat", 
                        "typeData=" + (typeData == null ? "null" : typeData.dataType())
                ));
                if (typeData != null && typeData.hasData()) {
                    LogHelper.info(this, CareTraceLogSupport.format(
                            traceId, sessionId, "workbench_multi_turn", "使用上一轮数据筛选，类型：" + typeData.dataType()
                    ));
                    return Flux.concat(
                                    Flux.just("好的，我基于刚才的数据为你筛选...\n"),
                                    parser.generateAnswerWithHistory(traceId, sessionId, typeData.dataJson(), typeData.dataType(), message),
                                    Flux.just("\n以上就是筛选后的内容啦~")
                                )
                                .doOnComplete(()-> LogHelper.info(this, CareTraceLogSupport.format(
                                        traceId, sessionId, "workbench_chat_complete", "流式返回完成"
                                )))
                                .doOnError(err -> LogHelper.error(this, CareTraceLogSupport.format(
                                        traceId, sessionId, "workbench_error", "异常：" + err.getMessage()
                                ), err));
                }
            }

            // 6. 查库获取数据
            // 跨类型切换/全量查询/含业务关键词：传入 null 不继承筛选条件；否则传入 state 继承筛选条件
            WorkbenchConversationState parseState = (isCrossTypeSwitch || isFullDataQuery || isReQueryWithKeyword) ? null : state;

            Object data;
            String dataType;
            if (WorkbenchIntent.QUERY_DEPARTMENT_WORK.equals(intent)) {
                DepartmentWorkDto dto = parser.understandWork(traceId, sessionId, message, parseState);
                QueryDto queryDto = new QueryDto(dto.getWorkGroupContain(), dto.getManagerUser(), sessionId);
                JsonNode jsonNode = remoteService.queryValidAuthority(queryDto);
                if(jsonNode != null){
                    int code = jsonNode.path("code").asInt();
                    String msg = jsonNode.path("msg").asText();
                    if( code == HttpStatus.FORBIDDEN.value()) {
                        return Flux.just(msg);
                    }
                }
                dto.sessionId = sessionId;
                data = remoteService.queryWork(dto);
                dataType = "重点工作";
            }
            else if (WorkbenchIntent.QUERY_ANNUAL_KPI.equals(intent)) {
                AnnualKpiDto dto = parser.understandKpi(traceId, sessionId, message, parseState);
                QueryDto queryDto = new QueryDto(dto.getWorkGroupContain(), dto.getManagerUser(), sessionId);
                JsonNode jsonNode = remoteService.queryValidAuthority(queryDto);
                if(jsonNode != null){
                    int code = jsonNode.path("code").asInt();
                    String msg = jsonNode.path("msg").asText();
                    if( code == HttpStatus.FORBIDDEN.value()) {
                        return Flux.just(msg);
                    }
                }
                dto.sessionId = sessionId;
                data = remoteService.queryKpi(dto);
                dataType = "部门 KPI";
            }
            else if (WorkbenchIntent.QUERY_DEPARTMENT_MINUTES.equals(intent)) {
                DepartmentMinutesDto dto = parser.understandMinutes(traceId, sessionId, message, parseState);
                QueryDto queryDto = new QueryDto(dto.getWorkGroup(), dto.getManagerName(), sessionId);
                JsonNode jsonNode = remoteService.queryValidAuthority(queryDto);
                if(jsonNode != null){
                    int code = jsonNode.path("code").asInt();
                    String msg = jsonNode.path("msg").asText();
                    if( code == HttpStatus.FORBIDDEN.value()) {
                        return Flux.just(msg);
                    }
                }
                dto.sessionId = sessionId;
                data = remoteService.queryMinutes(dto);
                dataType = "会议跟踪";
            }
            else {
                return Flux.just("我是您的员工看板智能助手，目前只能支持查询重点工作、KPI、会议纪要相关信息哦~\n"
                        +"我可以例举几个问题提供帮助哦~\n"
                        +"1.查询本年度重点工作的详细信息\n"
                        +"2.查询本年度 KPI 的详细信息\n"
                        +"3.查询本年度会议纪要的详细信息");
            }

            // 6. 保存状态（包含数据 JSON）
            String dataJson = JsonUtils.objectToJson(data);
            LogHelper.info(this, CareTraceLogSupport.format(
                    traceId, sessionId, "save_state_before", 
                    "准备保存状态，sessionId=" + sessionId + ", intent=" + intent + ", dataType=" + dataType + ", dataJson 长度=" + (dataJson != null ? dataJson.length() : 0)
            ));
            if (state == null) {
                // 首次查询，创建新状态
                WorkbenchConversationState newState = WorkbenchConversationState.initial(sessionId, intent, Map.of(), dataType, dataJson);
                LogHelper.info(this, CareTraceLogSupport.format(
                        traceId, sessionId, "save_state_new", 
                        "创建新状态，newState.sessionId=" + newState.sessionId() + ", lastIntent=" + newState.lastIntent()
                ));
                conversationStateService.save(newState);
            } else {
                // 更新对应类型的状态
                WorkbenchConversationState newState = state.update(intent, Map.of());
                // 更新当前类型的数据
                newState.saveDataForType(dataType, intent, dataJson, Map.of());
                LogHelper.info(this, CareTraceLogSupport.format(
                        traceId, sessionId, "save_state_update", 
                        "更新状态，newState.sessionId=" + newState.sessionId() + ", lastIntent=" + newState.lastIntent()
                ));
                conversationStateService.save(newState);
            }
            LogHelper.info(this, CareTraceLogSupport.format(
                    traceId, sessionId, "save_state_after", 
                    "状态保存完成"
            ));

            return Flux.concat(
                            Flux.just("我这就为你查询" + dataType + "信息，请稍候...\n"),
                            parser.generateAnswer(traceId, sessionId, dataJson),
                            Flux.just("\n以上就是你要的全部内容啦~")
                    )
                    .doOnComplete(()-> LogHelper.info(this, CareTraceLogSupport.format(
                            traceId, sessionId, "workbench_chat_complete", "流式返回完成"
                    )))
                    .doOnError(err -> LogHelper.error(this, CareTraceLogSupport.format(
                            traceId, sessionId, "workbench_error", "异常：" + err.getMessage()
                    ), err));

        } catch (Exception e) {
            LogHelper.error(this, CareTraceLogSupport.format(
                    traceId, sessionId, "workbench_error", "执行失败：" + e.getMessage()
            ), e);
            return Flux.just("查询失败，请稍后重试");
        }
    }

    /**
     * 根据意图获取对应的类型数据
     */
    private WorkbenchConversationState.TypeData getTypeDataForIntent(WorkbenchConversationState state, WorkbenchIntent intent) {
        if (state == null) return null;

        Map<String, WorkbenchConversationState.TypeData> typeDataMap = state.getTypeDataMap();
        if (typeDataMap == null || typeDataMap.isEmpty()) return null;

        // 按意图匹配数据类型
        switch (intent) {
            case QUERY_DEPARTMENT_WORK:
                return typeDataMap.get("重点工作");
            case QUERY_ANNUAL_KPI:
                return typeDataMap.get("部门 KPI");
            case QUERY_DEPARTMENT_MINUTES:
                return typeDataMap.get("会议跟踪");
            default:
                return null;
        }
    }

    // ====================== 【工具方法：判断是否全量查询】 ======================
    private boolean isFullDataQuery(String message) {
        if (!org.springframework.util.StringUtils.hasText(message)) return false;
        String m = message.toLowerCase();
        return
                   m.contains("全量")
                || m.contains("全部")
                || m.contains("所有")
                || m.contains("重置")
                || m.contains("清除")
                || m.contains("不带筛选")
                || m.contains("无条件");
    }

    // ====================== 【工具方法：判断是否包含业务类型关键词（重新查库）】 ======================
    private boolean isReQueryWithKeyword(String message, WorkbenchIntent intent) {
        if (!org.springframework.util.StringUtils.hasText(message)) return false;
        String m = message.toLowerCase();
        return switch (intent) {
            case QUERY_ANNUAL_KPI -> 
                m.contains("kpi") || m.contains("绩效") || m.contains("指标");
            case QUERY_DEPARTMENT_WORK -> 
                m.contains("重点") || m.contains("工作") || m.contains("任务");
            case QUERY_DEPARTMENT_MINUTES -> 
                m.contains("会议") || m.contains("纪要") || m.contains("督办") || m.contains("跟踪");
            default -> false;
        };
    }
}
