package com.rj.controller;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rj.common.AudioAnalysisSceneType;
import com.rj.entity.AudioManagement;
import com.rj.entity.AudioTextAnalysisFurniture;
import com.rj.entity.AudioTextAnalysisSop;
import com.rj.entity.TodoItem;
import com.rj.service.IAudioManagementService;
import com.rj.service.IAudioTextAnalysisFurnitureService;
import com.rj.service.IAudioTextAnalysisSopService;
import com.rj.service.IAudioTextAnalysisLlmService;
import com.rj.service.ITodoItemService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.UUID;

/**
 * 音频文本-家具意向分析 控制器
 */
@RestController
@RequestMapping("/api/audioTextAnalysisFurniture")
@Tag(name = "语音分析-家具意向", description = "音频文本家具意向分析接口")
@Slf4j
public class AudioTextAnalysisFurnitureController {

    @Autowired
    private IAudioTextAnalysisFurnitureService furnitureService;

    @Autowired
    private IAudioManagementService audioManagementService;

    @Autowired
    private ITodoItemService todoItemService;

    @Autowired
    private IAudioTextAnalysisSopService sopService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private IAudioTextAnalysisLlmService audioTextAnalysisLlmService;

    // 兼容旧代码的字段声明（已不再在控制层使用，实际逻辑已迁移到业务层）
    private static final String SYSTEM_PROMPT_PATH = "prompts/audio_text_analysis_furniture_system.txt";
    private static final String USER_PROMPT_PATH = "prompts/audio_text_analysis_furniture_user.txt";
    private static String cachedSystemPrompt;
    private static String cachedUserPromptTemplate;

    @PostMapping("/add")
    @Operation(summary = "新增记录", description = "新增一条家具意向分析记录")
    public ResponseEntity<Map<String, Object>> add(@RequestBody AudioTextAnalysisFurniture furniture) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (furniture.getId() == null || furniture.getId().trim().isEmpty()) {
                furniture.setId(UUID.randomUUID().toString());
            }
            LocalDateTime now = LocalDateTime.now();
            furniture.setCreatedAt(now);
            furniture.setUpdatedAt(now);
            boolean success = furnitureService.save(furniture);
            result.put("success", success);
            result.put("data", furniture);
            result.put("message", success ? "新增成功" : "新增失败");
            return success ? ResponseEntity.ok(result) : ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            log.error("新增家具意向分析失败", e);
            result.put("success", false);
            result.put("message", "新增异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @PutMapping("/update")
    @Operation(summary = "修改记录", description = "更新一条家具意向分析记录")
    public ResponseEntity<Map<String, Object>> update(@RequestBody AudioTextAnalysisFurniture furniture) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (furniture.getId() == null || furniture.getId().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "ID不能为空");
                return ResponseEntity.badRequest().body(result);
            }
            furniture.setUpdatedAt(LocalDateTime.now());
            boolean success = furnitureService.updateById(furniture);
            result.put("success", success);
            result.put("message", success ? "更新成功" : "更新失败");
            result.put("data", furniture);
            return success ? ResponseEntity.ok(result) : ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            log.error("更新家具意向分析失败", e);
            result.put("success", false);
            result.put("message", "更新异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @DeleteMapping("/delete/{id}")
    @Operation(summary = "删除记录", description = "根据ID删除家具意向分析记录")
    public ResponseEntity<Map<String, Object>> delete(@PathVariable String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean success = furnitureService.removeById(id);
            result.put("success", success);
            result.put("message", success ? "删除成功" : "删除失败");
            return success ? ResponseEntity.ok(result) : ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            log.error("删除家具意向分析失败", e);
            result.put("success", false);
            result.put("message", "删除异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/page")
    @Operation(summary = "分页查询", description = "根据条件分页查询家具意向分析记录")
    public ResponseEntity<Map<String, Object>> page(
            @Parameter(description = "页码", example = "1")
            @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小", example = "10")
            @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "父ID/音频管理ID") @RequestParam(required = false) String parentId,
            @Parameter(description = "客户类型") @RequestParam(required = false) String customerType,
            @Parameter(description = "装修风格") @RequestParam(required = false) String decorationStyle,
            @Parameter(description = "所属人电话") @RequestParam(required = false) String ownerPhone,
            @Parameter(description = "客户电话") @RequestParam(required = false) String customerPhone,
            @Parameter(description = "创建开始时间", example = "2025-01-01 00:00:00")
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdStart,
            @Parameter(description = "创建结束时间", example = "2025-12-31 23:59:59")
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdEnd) {
        Map<String, Object> result = new HashMap<>();
        try {
            Page<AudioTextAnalysisFurniture> page = new Page<>(current, size);
            LambdaQueryWrapper<AudioTextAnalysisFurniture> wrapper = new LambdaQueryWrapper<>();
            if (parentId != null && !parentId.trim().isEmpty()) {
                wrapper.eq(AudioTextAnalysisFurniture::getParentId, parentId);
            }
            if (customerType != null && !customerType.trim().isEmpty()) {
                wrapper.eq(AudioTextAnalysisFurniture::getCustomerType, customerType);
            }
            if (decorationStyle != null && !decorationStyle.trim().isEmpty()) {
                wrapper.like(AudioTextAnalysisFurniture::getDecorationStyle, decorationStyle);
            }
            if (ownerPhone != null && !ownerPhone.trim().isEmpty()) {
                wrapper.like(AudioTextAnalysisFurniture::getOwnerPhone, ownerPhone);
            }
            if (customerPhone != null && !customerPhone.trim().isEmpty()) {
                wrapper.like(AudioTextAnalysisFurniture::getCustomerPhone, customerPhone);
            }
            if (createdStart != null) {
                wrapper.ge(AudioTextAnalysisFurniture::getCreatedAt, createdStart);
            }
            if (createdEnd != null) {
                wrapper.le(AudioTextAnalysisFurniture::getCreatedAt, createdEnd);
            }
            wrapper.orderByDesc(AudioTextAnalysisFurniture::getUpdatedAt);

            Page<AudioTextAnalysisFurniture> dataPage = furnitureService.page(page, wrapper);
            result.put("success", true);
            result.put("message", "查询成功");
            result.put("data", dataPage.getRecords());
            result.put("total", dataPage.getTotal());
            result.put("current", dataPage.getCurrent());
            result.put("size", dataPage.getSize());
            result.put("pages", dataPage.getPages());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("分页查询家具意向分析失败", e);
            result.put("success", false);
            result.put("message", "查询异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @GetMapping("/byParentId")
    @Operation(summary = "根据parentId查询", description = "根据父ID查询所有家具意向分析记录")
    public ResponseEntity<Map<String, Object>> listByParentId(
            @Parameter(description = "父ID/音频管理ID", required = true)
            @RequestParam String parentId) {
        Map<String, Object> result = new HashMap<>();
        try {
            LambdaQueryWrapper<AudioTextAnalysisFurniture> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AudioTextAnalysisFurniture::getParentId, parentId)
                    .orderByDesc(AudioTextAnalysisFurniture::getUpdatedAt);
            List<AudioTextAnalysisFurniture> list = furnitureService.list(wrapper);
            result.put("success", true);
            result.put("message", "查询成功");
            result.put("data", list);
            result.put("count", list.size());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("根据parentId查询家具意向分析失败", e);
            result.put("success", false);
            result.put("message", "查询异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    @PostMapping("/generateSummary/{id}")
    @Operation(summary = "生成总结", description = "根据ID获取recordingText，调用大模型生成总结并保存")
    public ResponseEntity<Map<String, Object>> generateSummary(
            @Parameter(description = "家具意向分析记录ID", required = true)
            @PathVariable String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 1. 根据ID查询家具意向分析记录
            AudioManagement audioManagement = audioManagementService.getById(id);
            if (audioManagement == null) {
                result.put("success", false);
                result.put("message", "记录不存在");
                return ResponseEntity.badRequest().body(result);
            }
            // 2. 检查summary字段，如果已存在总结内容，直接返回提示，不进行AI分析
            String summary = audioManagement.getSummary();
            if (summary != null && !summary.trim().isEmpty()) {
                result.put("success", true);
                result.put("message", "AI分析已完成");
                result.put("data", audioManagement);
                return ResponseEntity.ok(result);
            }
            // 3. 获取录音文本
            String recordingText = audioManagement.getRecordingText();
            if (recordingText == null || recordingText.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "录音文本为空");
                return ResponseEntity.badRequest().body(result);
            }
            // 4. 通过业务层通用服务调用大模型生成总结并保存数据
            AudioTextAnalysisFurniture furniture = audioTextAnalysisLlmService.generateSummaryAndSave(
                    AudioAnalysisSceneType.SCENARIO_FURNITURE_SALE,
                    recordingText,
                    id,
                    audioManagement.getSalesName(),
                    audioManagement.getSalesPhone(),
                    audioManagement.getCustomerName(),
                    audioManagement.getCustomerPhone()
            );

            if (furniture != null) {
                result.put("success", true);
                result.put("message", "生成总结成功");
                result.put("data", furniture);
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", "生成总结并保存失败");
                return ResponseEntity.badRequest().body(result);
            }

        } catch (Exception e) {
            log.error("生成总结失败，ID: {}", id, e);
            result.put("success", false);
            result.put("message", "生成总结异常：" + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 调用大模型生成总结
     * 
     * @param furniture 家具意向分析对象
     * @param parentId 父ID（AudioManagement的ID）
     * @param ownerName 所属人姓名
     * @param ownerPhone 所属人电话
     * @param customerName 客户姓名
     * @param customerPhone 客户电话
     */
    private void generateSummaryByLLM(AudioTextAnalysisFurniture furniture, String parentId, String ownerName, String ownerPhone, 
            String customerName, String customerPhone) {
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        log.info("开始调用大模型生成总结");
        
        Generation gen = new Generation();
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content(getSystemPrompt())
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content(buildPrompt(furniture.getRecordingText()))
                .build();
        
        GenerationParam param = GenerationParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-plus")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();

        try {
            GenerationResult call = gen.call(param);
            String rawContent = call.getOutput().getChoices().get(0).getMessage().getContent();
            log.info("大模型生成总结完成，结果长度: {}，内容是：{}", rawContent.length(), rawContent);
            applyStructuredResult(furniture, rawContent, parentId, ownerName, ownerPhone, customerName, customerPhone);
        } catch (NoApiKeyException e) {
            log.error("API密钥未配置", e);
            throw new RuntimeException("API密钥未配置: " + e.getMessage(), e);
        } catch (InputRequiredException e) {
            log.error("输入参数错误", e);
            throw new RuntimeException("输入参数错误: " + e.getMessage(), e);
        } catch (Exception e) {
            log.error("调用大模型生成总结失败", e);
            throw new RuntimeException("调用大模型失败: " + e.getMessage(), e);
        } finally {
            // 记录结束时间并计算耗时
            long endTime = System.currentTimeMillis();
            long durationMillis = endTime - startTime;
            double durationSeconds = durationMillis / 1000.0;
            double durationMinutes = durationSeconds / 60.0;
            log.info("调用大模型耗时: {} 毫秒, {} 秒, {} 分钟", durationMillis, String.format("%.2f", durationSeconds), String.format("%.2f", durationMinutes));
        }
    }

    private String buildPrompt(String recordingText) {
        String template = getUserPromptTemplate();
        // 替换占位符
        return template.replace("{RECORDING_TEXT}", recordingText != null ? recordingText : "");
    }

    /**
     * 读取系统提示词
     * @return 系统提示词内容
     */
    private String getSystemPrompt() {
        if (cachedSystemPrompt == null) {
            cachedSystemPrompt = readResourceFile(SYSTEM_PROMPT_PATH);
            // 如果读取失败，使用默认值作为fallback
            if (cachedSystemPrompt == null || cachedSystemPrompt.trim().isEmpty()) {
                log.warn("无法读取系统提示词文件，使用默认值");
                cachedSystemPrompt = "你是一个专业的家居销售顾问助手，需要从录音文本中抽取结构化信息并输出JSON。必须严格按照要求输出JSON，不能包含额外文字。";
            }
        }
        return cachedSystemPrompt;
    }

    /**
     * 读取用户提示词模板
     * @return 用户提示词模板内容
     */
    private String getUserPromptTemplate() {
        if (cachedUserPromptTemplate == null) {
            cachedUserPromptTemplate = readResourceFile(USER_PROMPT_PATH);
            // 如果读取失败，使用默认值作为fallback
            if (cachedUserPromptTemplate == null || cachedUserPromptTemplate.trim().isEmpty()) {
                log.warn("无法读取用户提示词模板文件，使用默认值");
                cachedUserPromptTemplate = buildDefaultUserPrompt();
            }
        }
        return cachedUserPromptTemplate;
    }

    /**
     * 读取资源文件内容
     * @param resourcePath 资源文件路径
     * @return 文件内容，如果读取失败返回null
     */
    private String readResourceFile(String resourcePath) {
        try {
            ClassLoader classLoader = getClass().getClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream(resourcePath);
            if (inputStream == null) {
                log.error("无法找到资源文件: {}", resourcePath);
                return null;
            }
            try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name()).useDelimiter("\\A")) {
                String content = scanner.hasNext() ? scanner.next() : "";
                log.info("成功读取提示词文件: {}, 长度: {}", resourcePath, content.length());
                return content;
            }
        } catch (Exception e) {
            log.error("读取资源文件失败: {}", resourcePath, e);
            return null;
        }
    }

    /**
     * 构建默认的用户提示词（作为fallback）
     * @return 默认提示词
     */
    private String buildDefaultUserPrompt() {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请阅读以下录音文本，从中提取客户信息并生成 JSON。必须覆盖所有字段，缺失信息请基于语境合理推断或标注\"暂无信息\"。\n\n");
        prompt.append("字段要求：\n");
        prompt.append("1. customer_type：客户类型，仅可填「新房装修」「二次翻修」「补充家居」。\n");
        prompt.append("2. family_structure：家庭结构，描述家庭几口人、几个孩子、几个老人，重点反应家庭成员。\n");
        prompt.append("3. intention_products：意向产品清单，比如：床、柜子、沙发等，仅限家居，不能扩展到其它产品，用顿号或逗号分隔。\n");
        prompt.append("4. summary：一句话总结，应该简洁明了地概括客户的需求和关键信息，重点关注客户预算（如果未提及，默认预算3万），关注的还有产品信息等关键信息。\n");
        prompt.append("5. decoration_style：装修风格，总结偏好的装修/家居风格，风格类型，并推测主人相关信息。\n");
        prompt.append("6. sofa：沙发需求或配置说明，大小、风格、数量、种类等相关信息。\n");
        prompt.append("7. tea_table：茶几/茶桌需求或配置，材质、风格。\n");
        prompt.append("8. dining_table：餐桌椅需求或配置。\n");
        prompt.append("9. study_desk：学习桌/书桌需求。\n");
        prompt.append("10. tv_cabinet：电视柜需求说明。\n");
        prompt.append("11. cabinet：橱柜或厨房柜体说明。\n");
        prompt.append("12. wine_cabinet：酒柜需求说明。\n");
        prompt.append("13. master_bedroom_cabinet：主卧衣柜/储物柜配置。\n");
        prompt.append("14. secondary_bedroom_cabinet：次卧衣柜/储物柜配置。\n");
        prompt.append("15. shoe_cabinet：鞋柜需求或配置。\n");
        prompt.append("16. bed_and_mattress：床及床垫配置。\n\n");
        
        prompt.append("重要：每个产品维度（sofa、tea_table、dining_table、study_desk、tv_cabinet、cabinet、wine_cabinet、master_bedroom_cabinet、secondary_bedroom_cabinet、shoe_cabinet、bed_and_mattress）必须是一个JSON对象，包含以下10个维度：\n");
        prompt.append("1. preferenceStyleAndColor：偏好风格与颜色\n");
        prompt.append("2. materialPreference：材质偏好\n");
        prompt.append("3. customerFocusAreas：客户重点关注\n");
        prompt.append("4. priceSensitivity：价格敏感度\n");
        prompt.append("5. activityParticipation：活动参与度\n");
        prompt.append("6. customerConcerns：客户疑虑点\n");
        prompt.append("7. deliveryService：交付服务\n");
        prompt.append("8. competitorFeedback：竞品反馈\n");
        prompt.append("9. deliveryCycle：交付周期\n");
        prompt.append("10. productAppearance：产品颜值\n\n");
        
        prompt.append("严格输出 JSON 格式，示例：\n");
        prompt.append("{\n");
        prompt.append("  \"customer_type\": \"二次翻修\",\n");
        prompt.append("  \"family_structure\": \"三口之家，一个小男孩\",\n");
        prompt.append("  \"intention_products\": \"床、沙发、酒柜、厨房柜子\",\n");
        prompt.append("  \"summary\": \"客户是二次翻修，对价格比较敏感，预算在10万以内\",\n");
        prompt.append("  \"decoration_style\": \"总结偏好的装修/家居风格，风格类型，并推测主人相关信息\",\n");
        prompt.append("  \"sofa\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"tea_table\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"dining_table\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"study_desk\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"tv_cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"wine_cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"master_bedroom_cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"secondary_bedroom_cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"shoe_cabinet\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  },\n");
        prompt.append("  \"bed_and_mattress\": {\n");
        prompt.append("    \"preferenceStyleAndColor\": \"偏好风格与颜色\",\n");
        prompt.append("    \"materialPreference\": \"材质偏好\",\n");
        prompt.append("    \"customerFocusAreas\": \"客户重点关注\",\n");
        prompt.append("    \"priceSensitivity\": \"价格敏感度\",\n");
        prompt.append("    \"activityParticipation\": \"活动参与度\",\n");
        prompt.append("    \"customerConcerns\": \"客户疑虑点\",\n");
        prompt.append("    \"deliveryService\": \"交付服务\",\n");
        prompt.append("    \"competitorFeedback\": \"竞品反馈\",\n");
        prompt.append("    \"deliveryCycle\": \"交付周期\",\n");
        prompt.append("    \"productAppearance\": \"产品颜值\"\n");
        prompt.append("  }\n");
        prompt.append("}\n\n");
        prompt.append("注意：\n");
        prompt.append("1. 必须严格按照JSON格式输出，不要添加任何额外文字或markdown代码块标记。\n");
        prompt.append("2. 每个产品维度必须是一个完整的JSON对象，包含上述10个维度。\n");
        prompt.append("3. 如果录音文本中未提及某个产品，该产品的JSON对象中所有维度应填写\"暂无信息\"或基于语境合理推断。\n");
        prompt.append("4. 所有字段值必须基于录音文本内容，合理推断，不能随意编造。\n\n");
        prompt.append("录音文本：\n{RECORDING_TEXT}");
        
        return prompt.toString();
    }

    private void applyStructuredResult(AudioTextAnalysisFurniture furniture, String rawContent, String parentId, String ownerName, String ownerPhone, 
            String customerName, String customerPhone) {
        String normalized = normalizeJson(rawContent);
        try {
            JsonNode root = objectMapper.readTree(normalized);
            // 基础字段
            furniture.setCustomerType(textValue(root, "customer_type"));
            furniture.setFamilyStructure(textValue(root, "family_structure"));
            furniture.setIntentionProducts(textValue(root, "intention_products"));
            furniture.setSummarySentence(textValue(root, "summary"));
            furniture.setDecorationStyle(textValue(root, "decoration_style"));
            
            // 产品维度字段，每个都是JSON对象，需要转换为JSON字符串
            furniture.setSofa(jsonObjectToString(root, "sofa"));
            furniture.setTeaTable(jsonObjectToString(root, "tea_table"));
            furniture.setDiningTable(jsonObjectToString(root, "dining_table"));
            furniture.setStudyDesk(jsonObjectToString(root, "study_desk"));
            furniture.setTvCabinet(jsonObjectToString(root, "tv_cabinet"));
            furniture.setCabinet(jsonObjectToString(root, "cabinet"));
            furniture.setWineCabinet(jsonObjectToString(root, "wine_cabinet"));
            furniture.setMasterBedroomCabinet(jsonObjectToString(root, "master_bedroom_cabinet"));
            furniture.setSecondaryBedroomCabinet(jsonObjectToString(root, "secondary_bedroom_cabinet"));
            furniture.setShoeCabinet(jsonObjectToString(root, "shoe_cabinet"));
            furniture.setBedAndMattress(jsonObjectToString(root, "bed_and_mattress"));
            furniture.setSummary1(jsonObjectToString(root, "summary1"));
            furniture.setSummary2(jsonObjectToString(root, "summary2"));
            furniture.setSummary3(jsonObjectToString(root, "summary3"));
            // 解析并保存待办事项
            saveTodoItems(root, parentId, ownerName, ownerPhone);
            // 解析并保存SOP评分信息
            saveSopInfo(root, parentId, ownerName, ownerPhone, customerName, customerPhone);
        } catch (JsonProcessingException e) {
            log.warn("解析大模型返回JSON失败，使用原始内容作为总结: {}", e.getMessage());
            furniture.setSummarySentence(rawContent);
        }
    }
    
    /**
     * 解析并保存待办事项
     * 
     * @param root JSON根节点
     * @param parentId 父ID（AudioManagement的ID）
     * @param ownerName 所属人姓名
     * @param ownerPhone 所属人电话
     */
    private void saveTodoItems(JsonNode root, String parentId, String ownerName, String ownerPhone) {
        try {
            JsonNode todoItemsNode = root.get("todo_item");
            if (todoItemsNode == null || !todoItemsNode.isArray()) {
                log.info("未找到待办事项数组或格式不正确");
                return;
            }
            
            LocalDateTime now = LocalDateTime.now();
            int savedCount = 0;
            
            for (JsonNode todoItemNode : todoItemsNode) {
                if (!todoItemNode.isObject()) {
                    log.warn("待办事项项不是JSON对象，跳过");
                    continue;
                }
                
                String todoTitle = textValue(todoItemNode, "todo_title");
                String todoDetail = textValue(todoItemNode, "todo_detail");
                
                // 如果标题和详情都为空，跳过
                if ((todoTitle == null || todoTitle.trim().isEmpty()) && 
                    (todoDetail == null || todoDetail.trim().isEmpty())) {
                    log.warn("待办事项标题和详情都为空，跳过");
                    continue;
                }
                
                TodoItem todoItem = new TodoItem();
                todoItem.setId(UUID.randomUUID().toString());
                todoItem.setParentId(parentId);
                todoItem.setTodoTitle(todoTitle != null ? todoTitle.trim() : "");
                todoItem.setTodoDetail(todoDetail != null ? todoDetail.trim() : "");
                todoItem.setOwnerName(ownerName);
                todoItem.setOwnerPhone(ownerPhone);
                todoItem.setStatus("待处理"); // 默认状态
                todoItem.setCreateTime(now);
                todoItem.setUpdateTime(now);
                todoItem.setPendingDate(now.plusDays(3)); // 延期处理时间为当前时间加三天
                boolean success = todoItemService.save(todoItem);
                if (success) {
                    savedCount++;
                    log.info("保存待办事项成功，ID: {}, 标题: {}", todoItem.getId(), todoItem.getTodoTitle());
                } else {
                    log.warn("保存待办事项失败，标题: {}", todoItem.getTodoTitle());
                }
            }
            
            log.info("待办事项保存完成，共保存 {} 条", savedCount);
        } catch (Exception e) {
            log.error("保存待办事项时发生异常", e);
            // 不抛出异常，避免影响主流程
        }
    }

    private String normalizeJson(String content) {
        String trimmed = content.trim();
        if (trimmed.startsWith("```")) {
            int firstLineBreak = trimmed.indexOf('\n');
            int lastFence = trimmed.lastIndexOf("```");
            if (firstLineBreak >= 0 && lastFence > firstLineBreak) {
                trimmed = trimmed.substring(firstLineBreak + 1, lastFence).trim();
            }
        }
        return trimmed;
    }

    private String textValue(JsonNode root, String field) {
        JsonNode node = root.get(field);
        return node == null || node.isNull() ? null : node.asText();
    }

    /**
     * 将JSON对象节点转换为JSON字符串
     * 如果节点是对象，则转换为格式化的JSON字符串；如果是文本，直接返回；如果不存在或为null，返回null
     */
    private String jsonObjectToString(JsonNode root, String field) {
        JsonNode node = root.get(field);
        if (node == null || node.isNull()) {
            return null;
        }
        try {
            if (node.isObject()) {
                // 如果是JSON对象，转换为紧凑的JSON字符串
                return objectMapper.writeValueAsString(node);
            } else if (node.isTextual()) {
                // 如果是文本，直接返回
                return node.asText();
            } else {
                // 其他类型也转换为字符串
                return objectMapper.writeValueAsString(node);
            }
        } catch (JsonProcessingException e) {
            log.warn("转换JSON对象失败，字段: {}, 错误: {}", field, e.getMessage());
            return node.isTextual() ? node.asText() : node.toString();
        }
    }

    /**
     * 解析并保存SOP评分信息
     * 
     * @param root JSON根节点
     * @param parentId 父ID（AudioManagement的ID）
     * @param ownerName 所属人姓名
     * @param ownerPhone 所属人电话
     * @param customerName 客户姓名
     * @param customerPhone 客户电话
     */
    private void saveSopInfo(JsonNode root, String parentId, String ownerName, String ownerPhone, 
            String customerName, String customerPhone) {
        try {
            // 检查是否存在SOP相关字段
            JsonNode comprehensiveScoreNode = root.get("comprehensive_score");
            if (comprehensiveScoreNode == null) {
                log.info("未找到SOP评分信息，跳过保存");
                return;
            }

            AudioTextAnalysisSop sop = new AudioTextAnalysisSop();
            sop.setId(UUID.randomUUID().toString());
            sop.setParentId(parentId);
            sop.setOwnerName(ownerName);
            sop.setOwnerPhone(ownerPhone);
            sop.setCustomerName(customerName);
            sop.setCustomerPhone(customerPhone);
            sop.setIndustryType("furniture");
            
            // 解析SOP评分字段
            sop.setComprehensiveScore(intValue(root, "comprehensive_score"));
            sop.setScoreSummaryReason(textValue(root, "score_summary_reason"));
            sop.setGreetingIceBreaking(intValue(root, "greeting_ice_breaking"));
            sop.setBrandIntroduction(intValue(root, "brand_introduction"));
            sop.setGoldenThreeQuestions(intValue(root, "golden_three_questions"));
            sop.setNeedsGuidance(intValue(root, "needs_guidance"));
            sop.setServiceProgression(intValue(root, "service_progression"));
            sop.setReassuranceHandbook(intValue(root, "reassurance_handbook"));
            sop.setThreeLevelPricing(intValue(root, "three_level_pricing"));
            sop.setObjectionHandling(intValue(root, "objection_handling"));
            sop.setActivityImplantation(intValue(root, "activity_implantation"));
            sop.setClosingCooperation(intValue(root, "closing_cooperation"));
            sop.setProactiveWechatAdd(intValue(root, "proactive_wechat_add"));
            sop.setPoliteFarewell(intValue(root, "polite_farewell"));
            
            // 设置时间
            LocalDateTime now = LocalDateTime.now();
            sop.setCreatedAt(now);
            sop.setUpdatedAt(now);
            
            // 检查是否已存在相同parentId的记录，如果存在则更新，否则新增
            LambdaQueryWrapper<AudioTextAnalysisSop> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AudioTextAnalysisSop::getParentId, parentId);
            AudioTextAnalysisSop existingSop = sopService.getOne(wrapper);
            if (existingSop != null) {
                sop.setId(existingSop.getId());
                boolean success = sopService.updateById(sop);
                if (success) {
                    log.info("更新SOP评分信息成功，ID: {}, parentId: {}", sop.getId(), parentId);
                } else {
                    log.warn("更新SOP评分信息失败，parentId: {}", parentId);
                }
            } else {
                boolean success = sopService.save(sop);
                if (success) {
                    log.info("保存SOP评分信息成功，ID: {}, parentId: {}", sop.getId(), parentId);
                } else {
                    log.warn("保存SOP评分信息失败，parentId: {}", parentId);
                }
            }
        } catch (Exception e) {
            log.error("保存SOP评分信息时发生异常", e);
            // 不抛出异常，避免影响主流程
        }
    }

    /**
     * 从JSON节点中获取整数值
     * 
     * @param root JSON根节点
     * @param field 字段名
     * @return 整数值，如果不存在或为null则返回null
     */
    private Integer intValue(JsonNode root, String field) {
        JsonNode node = root.get(field);
        if (node == null || node.isNull()) {
            return null;
        }
        if (node.isInt()) {
            return node.asInt();
        } else if (node.isTextual()) {
            try {
                String text = node.asText();
                if (text == null || text.trim().isEmpty()) {
                    return null;
                }
                return Integer.parseInt(text.trim());
            } catch (NumberFormatException e) {
                log.warn("无法将字段 {} 的值 {} 转换为整数", field, node.asText());
                return null;
            }
        }
        return null;
    }
}

