package com.rj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rj.entity.KnowledgeBase;
import com.rj.mapper.KnowledgeBaseMapper;
import com.rj.service.IKnowledgeBaseService;
import com.rj.service.MinIOService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 知识库管理表 服务实现类
 * </p>
 *
 * @author 李中华 ,spllzh
 * @since 2025-01-27
 */
@Slf4j
@Service
public class KnowledgeBaseServiceImpl extends ServiceImpl<KnowledgeBaseMapper, KnowledgeBase> implements IKnowledgeBaseService {

    @Autowired
    private MinIOService minIOService;

    /**
     * 文本文件内容预览的最大字符数
     */
    private static final int MAX_FILE_CONTENT_PREVIEW_LENGTH = 500;

    /**
     * 默认状态
     */
    private static final String DEFAULT_STATUS = "已发布";

    /**
     * 支持的文本文件扩展名
     */
    private static final String[] TEXT_FILE_EXTENSIONS = {
        ".txt", ".md", ".json", ".xml", ".csv", ".log",
        ".properties", ".yml", ".yaml", ".html", ".htm",
        ".css", ".js", ".java", ".py", ".sql", ".sh", ".bat"
    };

    @Override
    public Map<String, Object> addKnowledge(KnowledgeBase knowledgeBase) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 生成UUID作为主键
            knowledgeBase.setId(UUID.randomUUID().toString().replace("-", ""));
            knowledgeBase.setCreateTime(LocalDateTime.now());
            knowledgeBase.setUpdateTime(LocalDateTime.now());
            
            // 设置默认值
            if (knowledgeBase.getViewCount() == null) {
                knowledgeBase.setViewCount(0);
            }
            if (knowledgeBase.getLikeCount() == null) {
                knowledgeBase.setLikeCount(0);
            }
            if (knowledgeBase.getSortOrder() == null) {
                knowledgeBase.setSortOrder(0);
            }
            if (knowledgeBase.getIsTop() == null) {
                knowledgeBase.setIsTop(false);
            }
            if (isBlank(knowledgeBase.getStatus())) {
                knowledgeBase.setStatus(DEFAULT_STATUS);
            }
            
            boolean success = this.save(knowledgeBase);
            if (success) {
                result.put("success", true);
                result.put("message", "知识添加成功");
                result.put("data", knowledgeBase);
            } else {
                result.put("success", false);
                result.put("message", "知识添加失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "知识添加异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> getKnowledgeById(String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            KnowledgeBase knowledge = this.getById(id);
            if (knowledge != null) {
                // 增加浏览次数
                knowledge.setViewCount(knowledge.getViewCount() + 1);
                this.updateById(knowledge);
                
                result.put("success", true);
                result.put("message", "查询成功");
                result.put("data", knowledge);
            } else {
                result.put("success", false);
                result.put("message", "知识不存在");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "查询异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> getKnowledgeList(Integer current, Integer size, String title, 
                                               String category, String industry, String creator, String status) {
        try {
            // 参数验证和默认值设置
            if (current == null || current < 1) {
                current = 1;
            }
            if (size == null || size < 1) {
                size = 10;
            }
            
            // 构建查询条件
            LambdaQueryWrapper<KnowledgeBase> queryWrapper = buildQueryWrapper(title, category, industry, creator, status);
            
            // 执行分页查询
            Page<KnowledgeBase> page = new Page<>(current, size);
            Page<KnowledgeBase> knowledgePage = this.page(page, queryWrapper);
            
            // 处理附件文件内容读取（可选，用于调试）
            processAttachmentFiles(knowledgePage.getRecords());
            
            // 构建返回结果
            return buildSuccessResult(knowledgePage);
            
        } catch (Exception e) {
            log.error("查询知识列表异常", e);
            return buildErrorResult("查询异常：" + e.getMessage());
        }
    }

    /**
     * 构建查询条件
     * 
     * @param title 标题（模糊查询）
     * @param category 分类
     * @param industry 行业
     * @param creator 创建人（模糊查询）
     * @param status 状态
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<KnowledgeBase> buildQueryWrapper(String title, String category, 
                                                               String industry, String creator, String status) {
        LambdaQueryWrapper<KnowledgeBase> queryWrapper = new LambdaQueryWrapper<>();
        
        // 标题模糊查询
        if (isNotBlank(title)) {
            queryWrapper.like(KnowledgeBase::getTitle, title.trim());
        }
        
        // 分类精确查询
        if (isNotBlank(category)) {
            queryWrapper.eq(KnowledgeBase::getCategory, category.trim());
        }
        
        // 行业精确查询
        if (isNotBlank(industry)) {
            queryWrapper.eq(KnowledgeBase::getIndustry, industry.trim());
        }
        
        // 创建人模糊查询
        if (isNotBlank(creator)) {
            queryWrapper.like(KnowledgeBase::getCreator, creator.trim());
        }
        
        // 状态精确查询
        if (isNotBlank(status)) {
            queryWrapper.eq(KnowledgeBase::getStatus, status.trim());
        }
        
        // 排序：置顶优先，然后按排序权重，最后按更新时间倒序
        queryWrapper.orderByDesc(KnowledgeBase::getIsTop)
                   .orderByDesc(KnowledgeBase::getSortOrder)
                   .orderByDesc(KnowledgeBase::getUpdateTime);
        
        return queryWrapper;
    }

    /**
     * 处理附件文件内容读取（用于调试和日志记录）
     * 注意：此操作可能影响性能，生产环境建议移除或改为异步处理
     * 
     * @param knowledgeList 知识库列表
     */
    private void processAttachmentFiles(List<KnowledgeBase> knowledgeList) {
        if (knowledgeList == null || knowledgeList.isEmpty()) {
            return;
        }
        
        knowledgeList.forEach(knowledgeBase -> {
            String attachmentUrl = knowledgeBase.getAttachmentUrl();
            if (isNotBlank(attachmentUrl)) {
                readAndLogAttachmentContent(knowledgeBase.getId(), attachmentUrl);
            }
        });
    }

    /**
     * 读取并记录附件文件内容
     * 
     * @param knowledgeId 知识库ID
     * @param attachmentUrl 附件URL
     */
    private void readAndLogAttachmentContent(String knowledgeId, String attachmentUrl) {
        try {
            log.debug("知识库ID: {}, 附件URL: {}", knowledgeId, attachmentUrl);
            
            // 从URL中提取对象名（文件名）
            String objectName = extractObjectNameFromUrl(attachmentUrl);
            if (isBlank(objectName)) {
                log.warn("无法从URL中提取对象名: {}", attachmentUrl);
                return;
            }
            
            log.debug("从MinIO读取文件: {}", objectName);
            
            // 只处理文本文件
            if (!isTextFile(objectName)) {
                log.debug("文件 {} 不是文本文件，跳过内容读取", objectName);
                return;
            }
            
            // 从MinIO下载文件
            InputStream inputStream = minIOService.downloadFile(objectName);
            if (inputStream == null) {
                log.warn("无法从MinIO下载文件: {}", objectName);
                return;
            }
            
            // 读取文件内容预览
            String fileContent = readTextFileContent(inputStream, MAX_FILE_CONTENT_PREVIEW_LENGTH);
            log.info("知识库ID: {}, 文件内容预览 (前{}字符):\n{}", 
                    knowledgeId, MAX_FILE_CONTENT_PREVIEW_LENGTH, fileContent);
                    
        } catch (Exception e) {
            log.error("读取MinIO文件内容失败，知识库ID: {}, 错误: {}", knowledgeId, e.getMessage(), e);
        }
    }

    /**
     * 构建成功结果
     * 
     * @param knowledgePage 分页结果
     * @return 结果Map
     */
    private Map<String, Object> buildSuccessResult(Page<KnowledgeBase> knowledgePage) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "查询成功");
        result.put("data", knowledgePage.getRecords());
        result.put("total", knowledgePage.getTotal());
        result.put("current", knowledgePage.getCurrent());
        result.put("size", knowledgePage.getSize());
        result.put("pages", knowledgePage.getPages());
        return result;
    }

    /**
     * 构建错误结果
     * 
     * @param message 错误消息
     * @return 结果Map
     */
    private Map<String, Object> buildErrorResult(String message) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        result.put("message", message);
        return result;
    }

    /**
     * 判断字符串是否不为空
     * 
     * @param str 字符串
     * @return 是否不为空
     */
    private boolean isNotBlank(String str) {
        return str != null && !str.trim().isEmpty();
    }

    /**
     * 判断字符串是否为空
     * 
     * @param str 字符串
     * @return 是否为空
     */
    private boolean isBlank(String str) {
        return str == null || str.trim().isEmpty();
    }

    @Override
    public Map<String, Object> updateKnowledge(KnowledgeBase knowledgeBase) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (knowledgeBase.getId() == null || knowledgeBase.getId().trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "知识ID不能为空");
                return result;
            }
            
            knowledgeBase.setUpdateTime(LocalDateTime.now());
            boolean success = this.updateById(knowledgeBase);
            
            if (success) {
                result.put("success", true);
                result.put("message", "知识信息更新成功");
                result.put("data", knowledgeBase);
            } else {
                result.put("success", false);
                result.put("message", "知识信息更新失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "更新异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> deleteKnowledge(String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean success = this.removeById(id);
            if (success) {
                result.put("success", true);
                result.put("message", "知识删除成功");
            } else {
                result.put("success", false);
                result.put("message", "知识删除失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> batchDeleteKnowledge(List<String> ids) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (ids == null || ids.isEmpty()) {
                result.put("success", false);
                result.put("message", "知识ID列表不能为空");
                return result;
            }
            
            boolean success = this.removeByIds(ids);
            if (success) {
                result.put("success", true);
                result.put("message", "批量删除成功，共删除 " + ids.size() + " 条记录");
            } else {
                result.put("success", false);
                result.put("message", "批量删除失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "批量删除异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> likeKnowledge(String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            KnowledgeBase knowledge = this.getById(id);
            if (knowledge != null) {
                knowledge.setLikeCount(knowledge.getLikeCount() + 1);
                knowledge.setUpdateTime(LocalDateTime.now());
                boolean success = this.updateById(knowledge);
                
                if (success) {
                    result.put("success", true);
                    result.put("message", "点赞成功");
                    result.put("data", knowledge);
                } else {
                    result.put("success", false);
                    result.put("message", "点赞失败");
                }
            } else {
                result.put("success", false);
                result.put("message", "知识不存在");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "点赞异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> toggleTopKnowledge(String id) {
        Map<String, Object> result = new HashMap<>();
        try {
            KnowledgeBase knowledge = this.getById(id);
            if (knowledge != null) {
                knowledge.setIsTop(!knowledge.getIsTop());
                knowledge.setUpdateTime(LocalDateTime.now());
                boolean success = this.updateById(knowledge);
                
                if (success) {
                    result.put("success", true);
                    result.put("message", knowledge.getIsTop() ? "置顶成功" : "取消置顶成功");
                    result.put("data", knowledge);
                } else {
                    result.put("success", false);
                    result.put("message", "操作失败");
                }
            } else {
                result.put("success", false);
                result.put("message", "知识不存在");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "操作异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> getKnowledgeStatistics() {
        Map<String, Object> result = new HashMap<>();
        try {
            long totalCount = this.count();
            
            // 按状态统计
            LambdaQueryWrapper<KnowledgeBase> publishedWrapper = new LambdaQueryWrapper<>();
            publishedWrapper.eq(KnowledgeBase::getStatus, "已发布");
            long publishedCount = this.count(publishedWrapper);
            
            LambdaQueryWrapper<KnowledgeBase> draftWrapper = new LambdaQueryWrapper<>();
            draftWrapper.eq(KnowledgeBase::getStatus, "草稿");
            long draftCount = this.count(draftWrapper);
            
            LambdaQueryWrapper<KnowledgeBase> topWrapper = new LambdaQueryWrapper<>();
            topWrapper.eq(KnowledgeBase::getIsTop, true);
            long topCount = this.count(topWrapper);
            
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("totalKnowledge", totalCount);
            statistics.put("publishedCount", publishedCount);
            statistics.put("draftCount", draftCount);
            statistics.put("topCount", topCount);
            
            result.put("success", true);
            result.put("message", "统计信息获取成功");
            result.put("data", statistics);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "统计信息获取异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> getCategories() {
        Map<String, Object> result = new HashMap<>();
        try {
            LambdaQueryWrapper<KnowledgeBase> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(KnowledgeBase::getCategory)
                       .groupBy(KnowledgeBase::getCategory);
            List<KnowledgeBase> categories = this.list(queryWrapper);
            
            List<String> categoryList = categories.stream()
                    .map(KnowledgeBase::getCategory)
                    .distinct()
                    .toList();
            
            result.put("success", true);
            result.put("message", "分类列表获取成功");
            result.put("data", categoryList);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "分类列表获取异常：" + e.getMessage());
        }
        return result;
    }

    @Override
    public Map<String, Object> getIndustries() {
        Map<String, Object> result = new HashMap<>();
        try {
            LambdaQueryWrapper<KnowledgeBase> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(KnowledgeBase::getIndustry)
                       .groupBy(KnowledgeBase::getIndustry);
            List<KnowledgeBase> industries = this.list(queryWrapper);
            
            List<String> industryList = industries.stream()
                    .map(KnowledgeBase::getIndustry)
                    .distinct()
                    .toList();
            
            result.put("success", true);
            result.put("message", "行业列表获取成功");
            result.put("data", industryList);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "行业列表获取异常：" + e.getMessage());
        }
        return result;
    }

    /**
     * 从MinIO URL中提取对象名（文件名）
     * MinIO URL格式通常是: http://endpoint/bucket/objectName 或 http://endpoint/bucket/objectName?参数
     * 
     * @param url MinIO文件URL
     * @return 对象名，如果提取失败返回null
     */
    private String extractObjectNameFromUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return null;
        }
        
        try {
            // 去掉查询参数
            String urlWithoutParams = url;
            if (url.contains("?")) {
                urlWithoutParams = url.substring(0, url.indexOf("?"));
            }
            
            // 按"/"分割URL，获取最后一个部分作为对象名
            // MinIO URL格式: http://endpoint/bucket/objectName
            String[] parts = urlWithoutParams.split("/");
            if (parts.length > 0) {
                // 获取最后一个非空部分作为对象名
                for (int i = parts.length - 1; i >= 0; i--) {
                    if (parts[i] != null && !parts[i].trim().isEmpty()) {
                        return parts[i];
                    }
                }
            }
            
            return null;
        } catch (Exception e) {
            log.error("从URL提取对象名失败: {}", url, e);
            return null;
        }
    }

    /**
     * 判断文件是否为文本文件
     * 
     * @param fileName 文件名
     * @return 是否为文本文件
     */
    private boolean isTextFile(String fileName) {
        if (isBlank(fileName)) {
            return false;
        }
        
        String lowerFileName = fileName.toLowerCase();
        for (String ext : TEXT_FILE_EXTENSIONS) {
            if (lowerFileName.endsWith(ext)) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 读取文本文件内容
     * 
     * @param inputStream 文件输入流
     * @param maxLength 最大读取长度（字符数）
     * @return 文件内容（限制长度）
     */
    private String readTextFileContent(InputStream inputStream, int maxLength) {
        if (inputStream == null) {
            return null;
        }
        
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line;
            int totalLength = 0;
            while ((line = reader.readLine()) != null && totalLength < maxLength) {
                if (totalLength + line.length() > maxLength) {
                    // 如果加上这一行会超过限制，只读取部分内容
                    int remaining = maxLength - totalLength;
                    content.append(line, 0, remaining);
                    content.append("\n...(内容已截断)");
                    break;
                }
                content.append(line).append("\n");
                totalLength += line.length() + 1; // +1 for newline
            }
        } catch (Exception e) {
            log.error("读取文件内容失败: {}", e.getMessage(), e);
            return "读取文件内容失败: " + e.getMessage();
        }
        
        return content.toString();
    }
}
