package com.test.bijihoudaun.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.bijihoudaun.entity.ImageName;
import com.test.bijihoudaun.entity.MarkdownFile;
import com.test.bijihoudaun.entity.MarkdownFileChunk;
import com.test.bijihoudaun.entity.MarkdownFileVO;
import com.test.bijihoudaun.mapper.ImageNameMapper;
import com.test.bijihoudaun.mapper.MarkdownFileMapper;
import com.test.bijihoudaun.service.MarkdownFileService;
import com.test.bijihoudaun.util.MarkdownImageExtractor;
import com.test.bijihoudaun.util.SecurityUtil;
import com.test.bijihoudaun.util.SnowflakeIdGenerator;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
@Transactional
public class MarkdownFileServiceImpl
        extends ServiceImpl<MarkdownFileMapper, MarkdownFile>
        implements MarkdownFileService {

    @Autowired
    MarkdownFileMapper markdownFileMapper;
    @Resource
    ImageNameMapper imageNameMapper;
    @Resource
    SnowflakeIdGenerator snowflakeIdGenerator;
    @Resource
    ImageNameSyncService imageNameSyncService;


    @Override
    public MarkdownFile updateMarkdownContent(MarkdownFile markdownFile) {
        long id;
        markdownFile.setUpdatedAt(new Date());
        if (ObjectUtil.isNull(markdownFile.getId()) || markdownFile.getId() == 0L) {
            long l = snowflakeIdGenerator.nextId();
            markdownFile.setId(l);
            markdownFile.setCreatedAt(new Date());
            this.save(markdownFile);
            id=l;
        } else {
            MarkdownFile existingFile = this.getById(markdownFile.getId());
            if (existingFile != null) {
                LambdaUpdateWrapper<MarkdownFile> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(MarkdownFile::getId, markdownFile.getId())
                        .set(MarkdownFile::getUpdatedAt, new Date());
                
                if (markdownFile.getTitle() != null) {
                    updateWrapper.set(MarkdownFile::getTitle, markdownFile.getTitle());
                }
                if (markdownFile.getContent() != null) {
                    updateWrapper.set(MarkdownFile::getContent, markdownFile.getContent());
                }
                if (markdownFile.getGroupingId() != null) {
                    updateWrapper.set(MarkdownFile::getGroupingId, markdownFile.getGroupingId());
                }
                if (markdownFile.getFileName() != null) {
                    updateWrapper.set(MarkdownFile::getFileName, markdownFile.getFileName());
                }
                if (markdownFile.getIsPrivate() != null) {
                    updateWrapper.set(MarkdownFile::getIsPrivate, markdownFile.getIsPrivate());
                }
                
                this.update(updateWrapper);
            } else {
                this.updateById(markdownFile);
            }
            id=markdownFile.getId();
        }

        List<String> strings = MarkdownImageExtractor.extractImageFilenames(markdownFile.getContent());
        // 修复：调用单独的 Service 处理异步逻辑
        imageNameSyncService.syncImageNames(id, strings);
        
        MarkdownFileVO result = markdownFileMapper.selectByIdWithGrouping(id);
        if (result != null) {
            // 确保 groupingId 被正确设置
            if (result.getGroupingId() == null && markdownFile.getGroupingId() != null) {
                result.setGroupingId(markdownFile.getGroupingId());
            }
            return result;
        }
        return markdownFile;
    }
    
    @Override
    public MarkdownFile getMarkdownById(Long id, boolean isAuthenticated) {
        MarkdownFile file = this.getById(id);
        if (file != null && !isAuthenticated && file.getIsPrivate() != null && file.getIsPrivate() == 1) {
            // 对于未认证用户，私密笔记只返回标题，内容置空
            file.setContent("");
            return file;
        }
        return file;
    }

    
    @Override
    public List<MarkdownFileVO> getFilesByGroupingId(Long groupingId) {
        return markdownFileMapper.selectByGroupingIdWithGrouping(groupingId);
    }
    
    @Override
    public boolean deleteMarkdownFile(Long id) {
        Long currentUserId = SecurityUtil.getCurrentUserId();
        LambdaUpdateWrapper<MarkdownFile> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(MarkdownFile::getId, id)
                .set(MarkdownFile::getIsDeleted, 1)
                .set(MarkdownFile::getDeletedAt, new Date())
                .set(MarkdownFile::getDeletedBy, currentUserId);
        return this.update(updateWrapper);
    }

    @Override
    public List<MarkdownFile> test() {
        return markdownFileMapper.selectList(null);
    }

    @Override
    public List<MarkdownFile> getAllMarkdownFiles() {
        return markdownFileMapper.selectList(null);
    }

    @Override
    public List<MarkdownFile> searchByTitle(String keyword, int page, int pageSize) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return List.of();
        }
        int offset = (page - 1) * pageSize;
        LambdaQueryWrapper<MarkdownFile> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(MarkdownFile::getTitle, keyword)
                .eq(MarkdownFile::getIsDeleted, 0)
                .orderByDesc(MarkdownFile::getUpdatedAt)
                .last("LIMIT " + offset + "," + pageSize);
        return this.list(queryWrapper);
    }

    @Override
    public MarkdownFile updateMarkdownTitle(Long id, String title) {
        MarkdownFile file = this.getById(id);
        if (ObjectUtil.isNotNull(file)) {
            file.setTitle(title);
            file.setUpdatedAt(new Date());
            this.updateById(file);
        }
        return file;
    }

    @Override
    public List<MarkdownFileVO> getRecentFiles(int limit) {
        return markdownFileMapper.selectRecentWithGrouping(limit);
    }

    @Override
    public MarkdownFileChunk getMarkdownChunk(Long id, int chunkIndex, int chunkSize, boolean isAuthenticated) {
        // 获取文件基本信息（不包含内容）
        MarkdownFileVO fileVO = markdownFileMapper.selectByIdWithGrouping(id);
        if (fileVO == null) {
            return null;
        }
        
        // 检查权限：私密笔记需要登录
        if (fileVO.getIsPrivate() != null && fileVO.getIsPrivate() == 1 && !isAuthenticated) {
            MarkdownFileChunk chunk = new MarkdownFileChunk();
            chunk.setFileId(id);
            chunk.setTitle(fileVO.getTitle());
            chunk.setIsPrivate(fileVO.getIsPrivate());
            chunk.setChunk("该笔记为私密笔记，请登录后查看");
            chunk.setChunkIndex(0);
            chunk.setTotalChunks(1);
            chunk.setHasMore(false);
            chunk.setTotalLength(0);
            chunk.setChunkLength(0);
            return chunk;
        }
        
        // 获取完整内容
        MarkdownFile file = this.getById(id);
        if (file == null || file.getContent() == null) {
            return null;
        }
        
        String fullContent = file.getContent();
        int totalLength = fullContent.length();
        
        // 如果文件小于 500KB（约50万字符），直接返回全部内容
        if (totalLength <= 500000) {
            MarkdownFileChunk chunk = new MarkdownFileChunk();
            chunk.setFileId(id);
            chunk.setTitle(file.getTitle());
            chunk.setIsPrivate(file.getIsPrivate());
            chunk.setChunk(fullContent);
            chunk.setChunkIndex(0);
            chunk.setTotalChunks(1);
            chunk.setHasMore(false);
            chunk.setTotalLength(totalLength);
            chunk.setChunkLength(totalLength);
            return chunk;
        }
        
        // 大文件分页加载
        // 计算总块数
        int totalChunks = (int) Math.ceil((double) totalLength / chunkSize);
        
        // 确保 chunkIndex 在有效范围内
        if (chunkIndex < 0) {
            chunkIndex = 0;
        }
        if (chunkIndex >= totalChunks) {
            chunkIndex = totalChunks - 1;
        }
        
        // 计算当前块的起止位置
        int start = chunkIndex * chunkSize;
        int end = Math.min(start + chunkSize, totalLength);
        
        // 截取内容
        String chunkContent = fullContent.substring(start, end);
        
        // 如果不是第一块，尝试从完整的换行处开始
        if (chunkIndex > 0 && start < totalLength) {
            // 找到第一个换行符，从下一行开始显示
            int firstNewLine = chunkContent.indexOf('\n');
            if (firstNewLine > 0) {
                chunkContent = chunkContent.substring(firstNewLine + 1);
            }
        }
        
        MarkdownFileChunk chunk = new MarkdownFileChunk();
        chunk.setFileId(id);
        chunk.setTitle(file.getTitle());
        chunk.setIsPrivate(file.getIsPrivate());
        chunk.setChunk(chunkContent);
        chunk.setChunkIndex(chunkIndex);
        chunk.setTotalChunks(totalChunks);
        chunk.setHasMore(chunkIndex < totalChunks - 1);
        chunk.setTotalLength(totalLength);
        chunk.setChunkLength(chunkContent.length());
        
        return chunk;
    }
}
