package com.seer.teach.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seer.teach.admin.service.MaterialUploadService;
import com.seer.teach.common.service.CommonFileService;
import com.seer.teach.teacher.module.entity.MaterialDocEntity;
import com.seer.teach.teacher.service.MaterialDocService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import jakarta.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MaterialUploadServiceImpl implements MaterialUploadService {

    @Autowired
    private MaterialDocService teacherMaterialDocService;
    
    @Autowired
    private CommonFileService commonFileService;

    @Override
    public MaterialDocEntity uploadMaterial(String originalFileName,File file, String jsonContent, String subject, String version, String volumeName, String grade) throws Exception {
        log.info("准备上传教材文件: {}, 学科: {}, 版本: {}, 年级: {}, 册别: {}",
                file.getName(), subject, version, grade, volumeName);

        // 获取文件MIME类型
        String mimeType = getMimeType(file);
        
        // 获取文件扩展名
        String fileExtension = getFileExtension(file.getName());
        
        // 获取文件格式描述
        String fileFormat = getFileFormat(fileExtension);

        // 计算文件大小（MB）
        BigDecimal fileSizeMB = new BigDecimal(file.length())
                .divide(new BigDecimal(1024 * 1024), 2, BigDecimal.ROUND_HALF_UP);

        // 计算文件MD5值
        String md5 = calculateMD5(file);
        List<MaterialDocEntity> materialDocs = teacherMaterialDocService.list(new LambdaQueryWrapper<>(MaterialDocEntity.class).eq(MaterialDocEntity::getTeacherMaterialMd5, md5));
        if( CollUtil.isNotEmpty(materialDocs)){
            throw new RuntimeException("已存在相同MD5值的教材文件,md5:" + md5);
        }
        String fileUrl = "";
        log.info("开始上传教材文件: {}, 学科: {}, 版本: {}, 年级: {}, 册别: {}",
                file.getName(), subject, version, grade, volumeName);
        // 上传文件到MinIO
        try (InputStream inputStream = new FileInputStream(file)) {
            fileUrl = commonFileService.uploadTextBook(inputStream, originalFileName, "PDF", mimeType);
            log.debug("文件上传到MinIO成功，URL: {}", fileUrl);
        } catch (Exception e) {
            log.error("文件上传到MinIO失败", e);
            throw e;
        }

        // 创建教师教材文档记录
        MaterialDocEntity materialDoc = new MaterialDocEntity();
        materialDoc.setTeacherMaterialDocName(originalFileName);
        materialDoc.setTeacherMaterialUrl(fileUrl);
        materialDoc.setTeacherMaterialSizeMb(fileSizeMB);
        materialDoc.setJsonContent(jsonContent);
        materialDoc.setFileFormat(fileFormat);
        materialDoc.setTeacherMaterialMime(mimeType);
        materialDoc.setTeacherMaterialExt(fileExtension);
        materialDoc.setTeacherMaterialMd5(md5);
        materialDoc.setSubjectName(subject);
        materialDoc.setVersionName(version);
        materialDoc.setGradeName(grade);
        materialDoc.setVolumeName(volumeName);
        materialDoc.setUploadTime(LocalDateTime.now());
        materialDoc.setMaterialStatus(1);
        // 保存到数据库
        teacherMaterialDocService.save(materialDoc);
        log.info("保存教材文档记录成功，ID: {}", materialDoc.getId());

        return materialDoc;
    }
    
    /**
     * 获取文件的MIME类型
     * @param file 文件
     * @return MIME类型
     */
    private String getMimeType(File file) {
        try {
            Path path = file.toPath();
            String mimeType = Files.probeContentType(path);
            String result = mimeType != null ? mimeType : "application/octet-stream";
            log.debug("获取文件MIME类型: {} -> {}", file.getName(), result);
            return result;
        } catch (Exception e) {
            log.warn("无法确定文件MIME类型，使用默认值: " + file.getName(), e);
            return "application/octet-stream";
        }
    }
    
    /**
     * 从文件名中提取扩展名
     * @param fileName 文件名
     * @return 文件扩展名（小写）
     */
    private String getFileExtension(String fileName) {
        if (fileName != null && fileName.contains(".")) {
            String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            log.debug("提取文件扩展名: {} -> {}", fileName, extension);
            return extension;
        }
        log.debug("文件无扩展名: {}", fileName);
        return "";
    }
    
    /**
     * 根据文件扩展名获取文件格式描述
     * @param extension 文件扩展名
     * @return 文件格式描述
     */
    private String getFileFormat(String extension) {
        if (extension == null || extension.isEmpty()) {
            log.debug("文件扩展名为空，返回格式: UNKNOWN");
            return "UNKNOWN";
        }
        
        String format;
        switch (extension.toLowerCase()) {
            case "pdf":
                format = "PDF";
                break;
            case "doc":
            case "docx":
                format = "WORD";
                break;
            case "xls":
            case "xlsx":
                format = "EXCEL";
                break;
            case "ppt":
            case "pptx":
                format = "PPT";
                break;
            case "jpg":
            case "jpeg":
                format = "JPEG";
                break;
            case "png":
                format = "PNG";
                break;
            case "mp4":
                format = "VIDEO";
                break;
            case "mp3":
                format = "AUDIO";
                break;
            default:
                format = extension.toUpperCase();
                break;
        }
        
        log.debug("确定文件格式: {} -> {}", extension, format);
        return format;
    }
    
    /**
     * 计算文件的MD5值
     * @param file 文件
     * @return MD5值
     * @throws Exception 计算过程中可能抛出的异常
     */
    private String calculateMD5(File file) throws Exception {
        try (InputStream inputStream = new FileInputStream(file)) {
            String md5 = DigestUtils.md5DigestAsHex(inputStream);
            log.debug("计算文件MD5值完成: {} -> {}", file.getName(), md5);
            return md5;
        }
    }
}