package org.xyzh.workcase.service;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.xyzh.api.file.dto.TbSysFileDTO;
import org.xyzh.api.workcase.dto.TbWorkcaseDTO;
import org.xyzh.api.workcase.dto.TbWorkcaseDeviceDTO;
import org.xyzh.api.workcase.dto.TbWorkcaseProcessDTO;
import org.xyzh.api.workcase.service.WorkcaseService;
import org.xyzh.common.auth.utils.LoginUtil;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.utils.id.IdUtil;
import org.xyzh.workcase.enums.WorkcaseProcessAction;
import org.xyzh.workcase.mapper.TbWorkcaseDeviceMapper;
import org.xyzh.workcase.mapper.TbWorkcaseMapper;
import org.xyzh.workcase.mapper.TbWorkcaseProcessMapper;
import org.xyzh.api.file.service.FileService;
import org.xyzh.api.workcase.dto.TbChatRoomDTO;
import org.xyzh.api.workcase.service.ChatRoomService;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@DubboService(version = "1.0.0",group = "workcase",timeout = 30000,retries = 0)
public class WorkcaseServiceImpl implements WorkcaseService {
    private static final Logger logger = LoggerFactory.getLogger(WorkcaseServiceImpl.class);

    @Autowired
    private TbWorkcaseMapper workcaseMapper;

    @Autowired
    private TbWorkcaseProcessMapper workcaseProcessMapper;

    @Autowired
    private TbWorkcaseDeviceMapper workcaseDeviceMapper;

    @Autowired
    private ChatRoomService chatRoomService;

    @DubboReference(version = "1.0.0",group = "file",timeout = 30000,retries = 0)
    private FileService fileService;

    // ====================== 工单管理 ======================

    @Override
    public ResultDomain<TbWorkcaseDTO> createWorkcase(TbWorkcaseDTO workcase) {
        logger.info("创建工单: userId={}, type={}, roomId={}", workcase.getUserId(), workcase.getType(), workcase.getRoomId());
        
        // 前端应确保 roomId 已创建并传入
        if (workcase.getRoomId() == null || workcase.getRoomId().isEmpty()) {
            logger.error("创建工单失败: roomId 不能为空");
            return ResultDomain.failure("缺少聊天室ID (roomId)，无法创建工单");
        }

        
        if (workcase.getWorkcaseId() == null || workcase.getWorkcaseId().isEmpty()) {
            workcase.setWorkcaseId(IdUtil.generateUUID());
        }
        if (workcase.getOptsn() == null || workcase.getOptsn().isEmpty()) {
            workcase.setOptsn(IdUtil.getOptsn());
        }
        if (workcase.getStatus() == null || workcase.getStatus().isEmpty()) {
            workcase.setStatus("pending");
        }
        if (workcase.getEmergency() == null || workcase.getEmergency().isEmpty()) {
            workcase.setEmergency("normal");
        }
        // 统一由后端从登录态设置 creator，避免前端传入不可信
        workcase.setCreator(LoginUtil.getCurrentUserId());

        // 解析设备铭牌二维码
        // ResultDomain<TbWorkcaseDeviceDTO> deviceResult = anylizeQrCode(workcase.getDeviceNamePlateImg());

        int rows = workcaseMapper.insertWorkcase(workcase);
        if (rows > 0) {
            // 创建工单处理记录
            TbWorkcaseProcessDTO process = new TbWorkcaseProcessDTO();
            process.setProcessId(IdUtil.generateUUID());
            process.setOptsn(IdUtil.getOptsn());
            process.setWorkcaseId(workcase.getWorkcaseId());
            process.setAction(WorkcaseProcessAction.CREATE.getName());
            process.setMessage("工单创建");
            process.setCreator(workcase.getCreator());
            workcaseProcessMapper.insertWorkcaseProcess(process);

            // 如果是新创建的聊天室，更新聊天室的 workcaseId

            logger.info("更新聊天室的工单ID: roomId={}, workcaseId={}", workcase.getRoomId(), workcase.getWorkcaseId());
            TbChatRoomDTO updateRoom = new TbChatRoomDTO();
            updateRoom.setRoomId(workcase.getRoomId());
            updateRoom.setWorkcaseId(workcase.getWorkcaseId());
            chatRoomService.updateChatRoom(updateRoom);

            // 插入设备文件记录到数据库
            // if (deviceResult.getSuccess() && deviceResult.getData() != null) {
            //     List<TbWorkcaseDeviceDTO> deviceList = (List<TbWorkcaseDeviceDTO>) deviceResult.getData();
            //     for (TbWorkcaseDeviceDTO deviceDTO : deviceList) {
            //         deviceDTO.setWorkcaseId(workcase.getWorkcaseId());
            //         try {
            //             workcaseDeviceMapper.insertWorkcaseDevice(deviceDTO);
            //             logger.info("设备文件记录插入成功: workcaseId={}, fileName={}",
            //                 workcase.getWorkcaseId(), deviceDTO.getFileName());
            //         } catch (Exception e) {
            //             logger.error("设备文件记录插入失败: " + deviceDTO.getFileName(), e);
            //         }
            //     }
            // }

            syncWorkcaseToCrm(workcase);
            return ResultDomain.success("创建成功", workcase);
            // return ResultDomain.success(deviceResult.getSuccess() ? "创建成功" : "设备铭牌二维码解析失败", workcase);
        }
        return ResultDomain.failure("创建失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDTO> updateWorkcase(TbWorkcaseDTO workcase) {
        logger.info("更新工单: workcaseId={}, status={}", workcase.getWorkcaseId(), workcase.getStatus());
        
        TbWorkcaseDTO existing = workcaseMapper.selectWorkcaseById(workcase.getWorkcaseId());
        if (existing == null) {
            return ResultDomain.failure("工单不存在");
        }
        
        String oldStatus = existing.getStatus();
        int rows = workcaseMapper.updateWorkcase(workcase);
        
        if (rows > 0) {
            TbWorkcaseDTO updated = workcaseMapper.selectWorkcaseById(workcase.getWorkcaseId());
            
            if (workcase.getStatus() != null && !workcase.getStatus().equals(oldStatus)) {
                TbWorkcaseProcessDTO process = new TbWorkcaseProcessDTO();
                process.setProcessId(IdUtil.generateUUID());
                process.setOptsn(IdUtil.getOptsn());
                process.setWorkcaseId(workcase.getWorkcaseId());
                process.setCreator(workcase.getCreator());
                
                if ("done".equals(workcase.getStatus())) {
                    process.setAction(WorkcaseProcessAction.FINISH.getName());
                    process.setMessage("工单完成");
                } else if ("cancelled".equals(workcase.getStatus())) {
                    process.setAction(WorkcaseProcessAction.REPEAL.getName());
                    process.setMessage("工单撤销");
                } else {
                    process.setAction(WorkcaseProcessAction.INFO.getName());
                    process.setMessage("状态变更: " + oldStatus + " -> " + workcase.getStatus());
                }
                workcaseProcessMapper.insertWorkcaseProcess(process);
            }
            
            syncWorkcaseToCrm(updated);
            
            return ResultDomain.success("更新成功", updated);
        }
        return ResultDomain.failure("更新失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDTO> deleteWorkcase(TbWorkcaseDTO workcase) {
        logger.info("删除工单: workcaseId={}", workcase.getWorkcaseId());
        
        int rows = workcaseMapper.deleteWorkcase(workcase);
        if (rows > 0) {
            return ResultDomain.success("删除成功", workcase);
        }
        return ResultDomain.failure("删除失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDTO> getWorkcaseById(String workcaseId) {
        TbWorkcaseDTO workcase = workcaseMapper.selectWorkcaseById(workcaseId);
        if (workcase != null) {
            return ResultDomain.success("查询成功", workcase);
        }
        return ResultDomain.failure("工单不存在");
    }

    @Override
    public ResultDomain<TbWorkcaseDTO> getWorkcaseList(TbWorkcaseDTO filter) {
        List<TbWorkcaseDTO> list = workcaseMapper.selectWorkcaseList(filter);
        return ResultDomain.success("查询成功", list);
    }

    @Override
    public ResultDomain<TbWorkcaseDTO> getWorkcasePage(PageRequest<TbWorkcaseDTO> pageRequest) {
        TbWorkcaseDTO filter = pageRequest.getFilter();
        PageParam pageParam = pageRequest.getPageParam();
        
        List<TbWorkcaseDTO> list = workcaseMapper.selectWorkcasePage(filter, pageParam);
        long total = workcaseMapper.countWorkcases(filter);
        
        pageParam.setTotal((int) total);
        PageDomain<TbWorkcaseDTO> pageDomain = new PageDomain<>(pageParam, list);
        return ResultDomain.success("查询成功", pageDomain);
    }

    // ====================== 同步到CRM和接收 ===================

    @Override
    public ResultDomain<Void> syncWorkcaseToCrm(TbWorkcaseDTO workcase) {
        logger.info("同步工单到CRM: workcaseId={}", workcase.getWorkcaseId());
        
        // ============== 伪代码：同步工单到CRM系统 ==============
        // 1. 构建CRM请求数据
        // JSONObject crmData = new JSONObject();
        // crmData.put("workcaseId", workcase.getWorkcaseId());
        // crmData.put("userId", workcase.getUserId());
        // crmData.put("username", workcase.getUsername());
        // crmData.put("phone", workcase.getPhone());
        // crmData.put("type", workcase.getType());
        // crmData.put("device", workcase.getDevice());
        // crmData.put("deviceCode", workcase.getDeviceCode());
        // crmData.put("emergency", workcase.getEmergency());
        // crmData.put("status", workcase.getStatus());
        // crmData.put("createTime", workcase.getCreateTime());
        
        // 2. 调用CRM接口
        // String crmApiUrl = "https://crm.example.com/api/workcase/sync";
        // HttpHeaders headers = new HttpHeaders();
        // headers.setContentType(MediaType.APPLICATION_JSON);
        // headers.set("Authorization", "Bearer " + crmToken);
        // HttpEntity<String> request = new HttpEntity<>(crmData.toJSONString(), headers);
        // ResponseEntity<String> response = restTemplate.postForEntity(crmApiUrl, request, String.class);
        
        // 3. 处理响应
        // if (response.getStatusCode() == HttpStatus.OK) {
        //     JSONObject result = JSON.parseObject(response.getBody());
        //     String crmWorkcaseId = result.getString("crmWorkcaseId");
        //     logger.info("同步成功，CRM工单ID: {}", crmWorkcaseId);
        // } else {
        //     logger.error("同步失败: {}", response.getBody());
        //     return ResultDomain.failure("同步CRM失败");
        // }
        // ============== 伪代码结束 ==============
        
        logger.info("CRM同步完成（伪代码）: workcaseId={}", workcase.getWorkcaseId());
        return ResultDomain.success("同步成功");
    }

    @Override
    public ResultDomain<Void> receiveWorkcaseFromCrm(JSONObject json) {
        logger.info("接收CRM工单更新");
        
        // ============== 伪代码：接收CRM的工单处理结果 ==============
        // 1. 解析CRM推送的数据
        // JSONObject crmData = (JSONObject) json;
        // String workcaseId = crmData.getString("workcaseId");
        // String status = crmData.getString("status");
        // String processor = crmData.getString("processor");
        // String message = crmData.getString("message");
        
        // 2. 更新本地工单
        // TbWorkcaseDTO workcase = new TbWorkcaseDTO();
        // workcase.setWorkcaseId(workcaseId);
        // workcase.setStatus(status);
        // workcase.setProcessor(processor);
        // workcaseMapper.updateWorkcase(workcase);
        
        // 3. 记录处理过程
        // TbWorkcaseProcessDTO process = new TbWorkcaseProcessDTO();
        // process.setProcessId(UUID.randomUUID().toString().replace("-", ""));
        // process.setOptsn(SnowflakeIdUtil.nextIdStr());
        // process.setWorkcaseId(workcaseId);
        // process.setAction(WorkcaseProcessAction.INFO.getName());
        // process.setMessage("CRM更新: " + message);
        // process.setProcessor(processor);
        // process.setCreator("CRM_SYSTEM");
        // workcaseProcessMapper.insertWorkcaseProcess(process);
        
        // 4. 如果工单完成或撤销，触发总结
        // if ("done".equals(status) || "cancelled".equals(status)) {
        //     workcaseChatService.summaryChat(workcaseId);
        // }
        // ============== 伪代码结束 ==============
        
        logger.info("CRM工单接收处理完成（伪代码）");
        return ResultDomain.success("接收成功");
    }

    private void sendWechatKefuWelcome(TbWorkcaseDTO workcase) {
        logger.info("发送微信客服欢迎语: workcaseId={}", workcase.getWorkcaseId());
        
        // ============== 伪代码：发送微信客服欢迎语 ==============
        // 1. 构建欢迎语内容（包含工单基本信息）
        // StringBuilder welcomeMsg = new StringBuilder();
        // welcomeMsg.append("【工单信息】\n");
        // welcomeMsg.append("工单编号：").append(workcase.getOptsn()).append("\n");
        // welcomeMsg.append("故障类型：").append(workcase.getType()).append("\n");
        // welcomeMsg.append("设备名称：").append(workcase.getDevice()).append("\n");
        // welcomeMsg.append("紧急程度：").append("emergency".equals(workcase.getEmergency()) ? "紧急" : "普通").append("\n");
        // welcomeMsg.append("联系人：").append(workcase.getUsername()).append("\n");
        // welcomeMsg.append("联系电话：").append(workcase.getPhone()).append("\n");
        // welcomeMsg.append("\n客服将尽快为您处理，请稍候...");
        
        // 2. 获取微信客服接入链接
        // String kefuUrl = wechatKefuService.getKefuUrl(workcase.getUserId());
        
        // 3. 调用微信客服API发送欢迎语
        // JSONObject msgBody = new JSONObject();
        // msgBody.put("touser", workcase.getUserId());  // 微信openid
        // msgBody.put("msgtype", "text");
        // JSONObject textContent = new JSONObject();
        // textContent.put("content", welcomeMsg.toString());
        // msgBody.put("text", textContent);
        
        // String accessToken = wechatService.getAccessToken();
        // String apiUrl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
        // restTemplate.postForEntity(apiUrl, msgBody.toJSONString(), String.class);
        
        // 4. 记录客服会话开始
        // wechatKefuService.startSession(workcase.getUserId(), workcase.getWorkcaseId());
        // ============== 伪代码结束 ==============
        
        logger.info("微信客服欢迎语发送完成（伪代码）: workcaseId={}", workcase.getWorkcaseId());
    }

    // ====================== 工单处理过程 ======================

    @Override
    public ResultDomain<TbWorkcaseProcessDTO> createWorkcaseProcess(TbWorkcaseProcessDTO workcaseProcess) {
        logger.info("创建工单过程: workcaseId={}, action={}", workcaseProcess.getWorkcaseId(), workcaseProcess.getAction());
        
        if (workcaseProcess.getProcessId() == null || workcaseProcess.getProcessId().isEmpty()) {
            workcaseProcess.setProcessId(IdUtil.generateUUID());
        }
        if (workcaseProcess.getOptsn() == null || workcaseProcess.getOptsn().isEmpty()) {
            workcaseProcess.setOptsn(IdUtil.getOptsn());
        }
        
        String action = workcaseProcess.getAction();
        if (WorkcaseProcessAction.ASSIGN.getName().equals(action) || 
            WorkcaseProcessAction.REDEPLOY.getName().equals(action)) {
            if (workcaseProcess.getProcessor() != null) {
                TbWorkcaseDTO workcase = new TbWorkcaseDTO();
                workcase.setWorkcaseId(workcaseProcess.getWorkcaseId());
                workcase.setProcessor(workcaseProcess.getProcessor());
                workcase.setStatus("processing");
                workcaseMapper.updateWorkcase(workcase);
            }
        } else if (WorkcaseProcessAction.FINISH.getName().equals(action)) {
            // 1. 更新工单状态为已完成
            TbWorkcaseDTO workcase = new TbWorkcaseDTO();
            workcase.setWorkcaseId(workcaseProcess.getWorkcaseId());
            workcase.setStatus("done");
            workcaseMapper.updateWorkcase(workcase);

            // 2. 发送系统评分消息到聊天室
            try {
                TbWorkcaseDTO workcaseData = workcaseMapper.selectWorkcaseById(workcaseProcess.getWorkcaseId());
                if (workcaseData != null && workcaseData.getRoomId() != null) {
                    // 创建系统评分消息
                    org.xyzh.api.workcase.dto.TbChatRoomMessageDTO commentMessage = new org.xyzh.api.workcase.dto.TbChatRoomMessageDTO();
                    commentMessage.setMessageId(IdUtil.generateUUID());
                    commentMessage.setOptsn(IdUtil.getOptsn());
                    commentMessage.setRoomId(workcaseData.getRoomId());
                    commentMessage.setSenderId("system");
                    commentMessage.setSenderType("system"); // 系统消息
                    commentMessage.setSenderName("系统");
                    commentMessage.setMessageType("comment"); // 评分消息
                    commentMessage.setContent("请为本次服务评分");
                    commentMessage.setStatus("sent");
                    commentMessage.setCreator("system");

                    // 发送消息到聊天室
                    chatRoomService.sendMessage(commentMessage);
                    logger.info("工单完成，已发送系统评分消息: workcaseId={}, roomId={}",
                        workcaseProcess.getWorkcaseId(), workcaseData.getRoomId());
                }
            } catch (Exception e) {
                logger.error("发送系统评分消息失败: workcaseId={}", workcaseProcess.getWorkcaseId(), e);
                // 不影响工单完成流程，只记录错误日志
            }
        } else if (WorkcaseProcessAction.REPEAL.getName().equals(action)) {
            TbWorkcaseDTO workcase = new TbWorkcaseDTO();
            workcase.setWorkcaseId(workcaseProcess.getWorkcaseId());
            workcase.setStatus("cancelled");
            workcaseMapper.updateWorkcase(workcase);
        }
        workcaseProcess.setCreator(LoginUtil.getCurrentUserId());
        
        int rows = workcaseProcessMapper.insertWorkcaseProcess(workcaseProcess);
        if (rows > 0) {
            TbWorkcaseDTO workcase = workcaseMapper.selectWorkcaseById(workcaseProcess.getWorkcaseId());
            if (workcase != null) {
                syncWorkcaseToCrm(workcase);
            }
            return ResultDomain.success("创建成功", workcaseProcess);
        }
        return ResultDomain.failure("创建失败");
    }

    @Override
    public ResultDomain<TbWorkcaseProcessDTO> updateWorkcaseProcess(TbWorkcaseProcessDTO workcaseProcess) {
        logger.info("更新工单过程: processId={}", workcaseProcess.getProcessId());
        
        int rows = workcaseProcessMapper.updateWorkcaseProcess(workcaseProcess);
        if (rows > 0) {
            TbWorkcaseProcessDTO updated = workcaseProcessMapper.selectWorkcaseProcessById(workcaseProcess.getProcessId());
            return ResultDomain.success("更新成功", updated);
        }
        return ResultDomain.failure("更新失败");
    }

    @Override
    public ResultDomain<TbWorkcaseProcessDTO> deleteWorkcaseProcess(TbWorkcaseProcessDTO workcaseProcess) {
        logger.info("删除工单过程: processId={}", workcaseProcess.getProcessId());
        
        int rows = workcaseProcessMapper.deleteWorkcaseProcess(workcaseProcess.getProcessId());
        if (rows > 0) {
            return ResultDomain.success("删除成功", workcaseProcess);
        }
        return ResultDomain.failure("删除失败");
    }

    @Override
    public ResultDomain<TbWorkcaseProcessDTO> getWorkcaseProcessList(TbWorkcaseProcessDTO filter) {
        List<TbWorkcaseProcessDTO> list = workcaseProcessMapper.selectWorkcaseProcessList(filter);
        return ResultDomain.success("查询成功", list);
    }

    @Override
    public ResultDomain<TbWorkcaseProcessDTO> getWorkcaseProcessPage(PageRequest<TbWorkcaseProcessDTO> pageRequest) {
        TbWorkcaseProcessDTO filter = pageRequest.getFilter();
        PageParam pageParam = pageRequest.getPageParam();
        
        List<TbWorkcaseProcessDTO> list = workcaseProcessMapper.selectWorkcaseProcessPage(filter, pageParam);
        long total = workcaseProcessMapper.countWorkcaseProcesses(filter);
        
        pageParam.setTotal((int) total);
        PageDomain<TbWorkcaseProcessDTO> pageDomain = new PageDomain<>(pageParam, list);
        return ResultDomain.success("查询成功", pageDomain);
    }

    // ====================== 工单设备管理 ======================

    @Override
    public ResultDomain<TbWorkcaseDeviceDTO> createWorkcaseDevice(TbWorkcaseDeviceDTO workcaseDevice) {
        logger.info("创建工单设备: workcaseId={}, device={}", workcaseDevice.getWorkcaseId(), workcaseDevice.getDevice());
        
        if (workcaseDevice.getOptsn() == null || workcaseDevice.getOptsn().isEmpty()) {
            workcaseDevice.setOptsn(IdUtil.getOptsn());
        }
        
        int rows = workcaseDeviceMapper.insertWorkcaseDevice(workcaseDevice);
        if (rows > 0) {
            return ResultDomain.success("创建成功", workcaseDevice);
        }
        return ResultDomain.failure("创建失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDeviceDTO> updateWorkcaseDevice(TbWorkcaseDeviceDTO workcaseDevice) {
        logger.info("更新工单设备: workcaseId={}, fileId={}", workcaseDevice.getWorkcaseId(), workcaseDevice.getFileId());
        
        int rows = workcaseDeviceMapper.updateWorkcaseDevice(workcaseDevice);
        if (rows > 0) {
            TbWorkcaseDeviceDTO updated = workcaseDeviceMapper.selectWorkcaseDeviceById(
                workcaseDevice.getWorkcaseId(), workcaseDevice.getFileId());
            return ResultDomain.success("更新成功", updated);
        }
        return ResultDomain.failure("更新失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDeviceDTO> deleteWorkcaseDevice(TbWorkcaseDeviceDTO workcaseDevice) {
        logger.info("删除工单设备: workcaseId={}, fileId={}", workcaseDevice.getWorkcaseId(), workcaseDevice.getFileId());
        
        int rows = workcaseDeviceMapper.deleteWorkcaseDevice(workcaseDevice.getWorkcaseId(), workcaseDevice.getFileId());
        if (rows > 0) {
            return ResultDomain.success("删除成功", workcaseDevice);
        }
        return ResultDomain.failure("删除失败");
    }

    @Override
    public ResultDomain<TbWorkcaseDeviceDTO> getWorkcaseDeviceList(TbWorkcaseDeviceDTO filter) {
        List<TbWorkcaseDeviceDTO> list = workcaseDeviceMapper.selectWorkcaseDeviceList(filter);
        return ResultDomain.success("查询成功", list);
    }

    @Override
    public ResultDomain<TbWorkcaseDeviceDTO> getWorkcaseDevicePage(PageRequest<TbWorkcaseDeviceDTO> pageRequest) {
        TbWorkcaseDeviceDTO filter = pageRequest.getFilter();
        PageParam pageParam = pageRequest.getPageParam();
        
        List<TbWorkcaseDeviceDTO> list = workcaseDeviceMapper.selectWorkcaseDevicePage(filter, pageParam);
        long total = workcaseDeviceMapper.countWorkcaseDevices(filter);
        
        pageParam.setTotal((int) total);
        PageDomain<TbWorkcaseDeviceDTO> pageDomain = new PageDomain<>(pageParam, list);
        return ResultDomain.success("查询成功", pageDomain);
    }

    /**
     * @description    扫描设备铭牌二维码，并下载其中的文件,构建WorkDeviceDTO列表
     * @param    qrcodeFileId    二维码文件id
     * @return    WorkDeviceDTO列表
     * @author    yslg
     * @since 2025-12-25
     */
    private ResultDomain<TbWorkcaseDeviceDTO> anylizeQrCode(String qrcodeFileId){
        List<TbWorkcaseDeviceDTO> workDeviceList = new ArrayList<>();

        try {
            logger.info("开始解析设备铭牌二维码: qrcodeFileId={}", qrcodeFileId);

            // 1. 从 FileService 获取二维码图片
            ResultDomain<byte[]> downloadResult = fileService.downloadFile(qrcodeFileId);
            if (!downloadResult.getSuccess()) {
                logger.error("下载二维码图片失败: {}", downloadResult.getMessage());
                return ResultDomain.failure("下载二维码图片失败: " + downloadResult.getMessage());
            }

            byte[] qrcodeImageBytes = downloadResult.getData();
            logger.info("二维码图片下载成功，大小: {} bytes", qrcodeImageBytes.length);

            // 2. 解析二维码内容
            String qrcodeContent = decodeQRCode(qrcodeImageBytes);
            if (qrcodeContent == null || qrcodeContent.isEmpty()) {
                logger.error("二维码解析失败或内容为空");
                return ResultDomain.failure("二维码解析失败或内容为空");
            }

            logger.info("二维码解析成功，内容: {}", qrcodeContent);

            // 3. 判断二维码内容类型并解析
            String deviceCode = null;
            String device = null;
            JSONArray files = null;

            // 尝试判断是 URL 还是 JSON
            if (qrcodeContent.startsWith("http://") || qrcodeContent.startsWith("https://")) {
                // 二维码包含 URL，需要访问 H5 页面解析
                logger.info("检测到二维码包含URL，开始访问页面: {}", qrcodeContent);
                JSONObject pageData = parseDevicePageFromUrl(qrcodeContent);

                if (pageData == null) {
                    logger.error("访问URL并解析页面失败");
                    return ResultDomain.failure("访问设备信息页面失败");
                }

                deviceCode = pageData.getString("deviceCode");
                device = pageData.getString("device");
                files = pageData.getJSONArray("files");
            } else {
                // 二维码直接包含 JSON 数据
                logger.info("检测到二维码包含JSON数据，直接解析");
                JSONObject qrcodeData = JSON.parseObject(qrcodeContent);
                deviceCode = qrcodeData.getString("deviceCode");
                device = qrcodeData.getString("device");
                files = qrcodeData.getJSONArray("files");
            }

            if (files == null || files.isEmpty()) {
                logger.warn("二维码中没有文件信息");
                return ResultDomain.success("二维码中没有文件信息", workDeviceList);
            }

            logger.info("设备编号: {}, 设备名称: {}, 文件数量: {}", deviceCode, device, files.size());

            // 4. 下载并存储每个文件
            for (int i = 0; i < files.size(); i++) {
                JSONObject fileInfo = files.getJSONObject(i);
                String fileName = fileInfo.getString("fileName");
                String fileUrl = fileInfo.getString("url");

                logger.info("开始下载文件 [{}/{}]: {}", i + 1, files.size(), fileName);

                try {
                    // 下载文件
                    byte[] fileBytes = downloadFileFromUrl(fileUrl);
                    if (fileBytes == null || fileBytes.length == 0) {
                        logger.error("文件下载失败: {}", fileName);
                        continue;
                    }

                    logger.info("文件下载成功: {}, 大小: {} bytes", fileName, fileBytes.length);

                    // 推断文件类型
                    String contentType = getContentTypeFromFileName(fileName);

                    // 通过 FileService 存储文件
                    ResultDomain<TbSysFileDTO> uploadResult = fileService.uploadFileBytes(
                        fileBytes,
                        fileName,
                        contentType,
                        "workcase",
                        deviceCode
                    );

                    if (uploadResult.getSuccess()) {
                        TbSysFileDTO uploadedFile = uploadResult.getData();
                        logger.info("文件上传成功: fileId={}, fileName={}", uploadedFile.getFileId(), fileName);

                        // 创建 TbWorkcaseDeviceDTO 对象
                        TbWorkcaseDeviceDTO deviceDTO = new TbWorkcaseDeviceDTO();
                        deviceDTO.setDevice(device);
                        deviceDTO.setDeviceCode(deviceCode);
                        deviceDTO.setFileId(uploadedFile.getFileId());
                        deviceDTO.setFileName(fileName);
                        deviceDTO.setFileRootId(uploadedFile.getFileRootId());
                        deviceDTO.setOptsn(IdUtil.getOptsn());

                        workDeviceList.add(deviceDTO);
                    } else {
                        logger.error("文件上传失败: {}, 原因: {}", fileName, uploadResult.getMessage());
                    }

                } catch (Exception e) {
                    logger.error("处理文件失败: " + fileName, e);
                }
            }

            logger.info("二维码解析完成，成功处理 {} 个文件", workDeviceList.size());
            return ResultDomain.success("解析成功，处理了 " + workDeviceList.size() + " 个文件", workDeviceList);

        } catch (Exception e) {
            logger.error("解析设备铭牌二维码失败", e);
            return ResultDomain.failure("解析设备铭牌二维码失败: " + e.getMessage());
        }
    }

    /**
     * 从 URL 解析设备页面信息
     */
    private JSONObject parseDevicePageFromUrl(String url) {
        try {
            logger.info("开始访问设备信息页面: {}", url);

            // 访问 URL 并获取 HTML 内容
            Document doc = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                    .timeout(10000)
                    .followRedirects(true)
                    .get();

            logger.info("页面访问成功，开始解析内容");

            // 解析设备编号和型号（从页面标题或特定元素中）
            String deviceInfo = doc.select("body").text();

            // 尝试匹配设备编号模式：数字格式如 202508012
            String deviceCode = null;
            String device = null;

            // 从页面内容中提取设备编号和型号
            if (deviceInfo.contains("(") && deviceInfo.contains(")")) {
                // 例如: "202508012 (THHM1800PL)"
                int start = deviceInfo.indexOf("(");
                int end = deviceInfo.indexOf(")", start);
                if (start > 0 && end > start) {
                    // 提取括号前的设备编号
                    String beforeBracket = deviceInfo.substring(Math.max(0, start - 20), start).trim();
                    String[] parts = beforeBracket.split("\\s+");
                    if (parts.length > 0) {
                        deviceCode = parts[parts.length - 1].trim();
                    }

                    // 提取括号内的型号
                    device = deviceInfo.substring(start + 1, end).trim();
                }
            }

            logger.info("提取的设备信息 - 编号: {}, 型号: {}", deviceCode, device);

            // 解析文件列表
            JSONArray files = new JSONArray();

            // 查找所有下载链接（通常是 PDF、图片等文件）
            Elements links = doc.select("a[href]");
            for (Element link : links) {
                String href = link.attr("abs:href"); // 获取绝对 URL
                String text = link.text().trim();

                // 过滤出文件下载链接（包含文件扩展名）
                if (isFileLink(href) && !text.isEmpty()) {
                    JSONObject fileInfo = new JSONObject();
                    fileInfo.put("fileName", text);
                    fileInfo.put("url", href);
                    files.add(fileInfo);
                    logger.info("发现文件: {} -> {}", text, href);
                }
            }

            // 如果没找到链接，尝试从 script 标签中查找 JSON 数据
            if (files.isEmpty()) {
                Elements scripts = doc.select("script");
                for (Element script : scripts) {
                    String scriptContent = script.html();
                    // 尝试查找 JSON 数据
                    if (scriptContent.contains("files") || scriptContent.contains("fileName")) {
                        try {
                            // 尝试解析嵌入的 JSON
                            int jsonStart = scriptContent.indexOf("{");
                            int jsonEnd = scriptContent.lastIndexOf("}") + 1;
                            if (jsonStart >= 0 && jsonEnd > jsonStart) {
                                String jsonStr = scriptContent.substring(jsonStart, jsonEnd);
                                JSONObject embedded = JSON.parseObject(jsonStr);
                                if (embedded.containsKey("files")) {
                                    files = embedded.getJSONArray("files");
                                    if (deviceCode == null) {
                                        deviceCode = embedded.getString("deviceCode");
                                    }
                                    if (device == null) {
                                        device = embedded.getString("device");
                                    }
                                    break;
                                }
                            }
                        } catch (Exception e) {
                            // 忽略解析错误，继续下一个 script
                        }
                    }
                }
            }

            if (deviceCode == null || files.isEmpty()) {
                logger.error("无法从页面中提取完整的设备信息");
                return null;
            }

            JSONObject result = new JSONObject();
            result.put("deviceCode", deviceCode);
            result.put("device", device != null ? device : "Unknown");
            result.put("files", files);

            logger.info("页面解析成功，设备编号: {}, 文件数量: {}", deviceCode, files.size());
            return result;

        } catch (Exception e) {
            logger.error("解析设备页面失败: " + url, e);
            return null;
        }
    }

    /**
     * 判断是否为文件下载链接
     */
    private boolean isFileLink(String url) {
        if (url == null || url.isEmpty()) {
            return false;
        }
        String lowerUrl = url.toLowerCase();
        return lowerUrl.endsWith(".pdf") ||
               lowerUrl.endsWith(".jpg") ||
               lowerUrl.endsWith(".jpeg") ||
               lowerUrl.endsWith(".png") ||
               lowerUrl.endsWith(".doc") ||
               lowerUrl.endsWith(".docx") ||
               lowerUrl.endsWith(".xls") ||
               lowerUrl.endsWith(".xlsx") ||
               lowerUrl.contains("/download") ||
               lowerUrl.contains("/file/") ||
               lowerUrl.contains(".pdf?") ||
               lowerUrl.contains(".jpg?");
    }

    /**
     * 解码二维码图片
     */
    private String decodeQRCode(byte[] imageBytes) {
        try {
            InputStream inputStream = new ByteArrayInputStream(imageBytes);
            BufferedImage bufferedImage = ImageIO.read(inputStream);

            if (bufferedImage == null) {
                logger.error("无法读取图片");
                return null;
            }

            BinaryBitmap binaryBitmap = new BinaryBitmap(
                new HybridBinarizer(
                    new BufferedImageLuminanceSource(bufferedImage)
                )
            );

            MultiFormatReader reader = new MultiFormatReader();
            java.util.Map<DecodeHintType, Object> hints = new java.util.HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

            Result result = reader.decode(binaryBitmap, hints);
            return result.getText();

        } catch (Exception e) {
            logger.error("解码二维码失败", e);
            return null;
        }
    }

    /**
     * 从URL下载文件
     */
    private byte[] downloadFileFromUrl(String fileUrl) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(URI.create(fileUrl));

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                if (response.getCode() == 200) {
                    return EntityUtils.toByteArray(response.getEntity());
                } else {
                    logger.error("下载文件失败，HTTP状态码: {}", response.getCode());
                    return null;
                }
            }
        } catch (Exception e) {
            logger.error("下载文件失败: " + fileUrl, e);
            return null;
        }
    }

    /**
     * 根据文件名推断 Content-Type
     */
    private String getContentTypeFromFileName(String fileName) {
        if (fileName == null) {
            return "application/octet-stream";
        }

        String lowerFileName = fileName.toLowerCase();
        if (lowerFileName.endsWith(".pdf")) {
            return "application/pdf";
        } else if (lowerFileName.endsWith(".jpg") || lowerFileName.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (lowerFileName.endsWith(".png")) {
            return "image/png";
        } else if (lowerFileName.endsWith(".doc")) {
            return "application/msword";
        } else if (lowerFileName.endsWith(".docx")) {
            return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        } else if (lowerFileName.endsWith(".xls")) {
            return "application/vnd.ms-excel";
        } else if (lowerFileName.endsWith(".xlsx")) {
            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        } else {
            return "application/octet-stream";
        }
    }

}
