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

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.admin.convert.AdminTeachTextConvert;
import com.seer.teach.admin.request.TeachTextVideoUpdateReq;
import com.seer.teach.admin.request.TeachTextsQueryReq;
import com.seer.teach.admin.request.TeachTextsReq;
import com.seer.teach.admin.response.TeachTextsResp;
import com.seer.teach.admin.service.AdminTeachTextsService;
import com.seer.teach.common.constants.CommonConstant;
import com.seer.teach.common.service.CommonFileService;
import com.seer.teach.teacher.module.entity.ModificationLogEntity;
import com.seer.teach.teacher.module.entity.TeachMethodsEntity;
import com.seer.teach.teacher.module.entity.TeachTextsEntity;
import com.seer.teach.teacher.service.TeachMethodsService;
import com.seer.teach.teacher.service.TeachTextsService;
import com.seer.teach.teacher.util.ModificationLogUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 教学文本管理服务实现类
 * </p>
 *
 * @author Lingma
 * @since 2025-12-04
 */
@Slf4j
@Service
public class AdminTeachTextsServiceImpl  implements AdminTeachTextsService {

    @Autowired
    private TeachTextsService teachTextsService;

    @Autowired
    private TeachMethodsService teachMethodsService;


    @Value("${video.upload.bucketName:textbook}")
    private String videoUploadBucketName;

    @Autowired
    private CommonFileService commonFileService;

    @Override
    public IPage<TeachTextsResp> pageTeachTexts(TeachTextsQueryReq req) {
        log.info("分页查询教学文本列表, 查询参数: {}", req);
        Page<TeachTextsEntity> page = new Page<>(req.getPageNo(), req.getPageSize());

        LambdaQueryWrapper<TeachTextsEntity> lambdaQuery = new LambdaQueryWrapper<>(TeachTextsEntity.class)
                .eq(req.getGoalId() != null, TeachTextsEntity::getGoalId, req.getGoalId())
                .eq(req.getMethodId() != null, TeachTextsEntity::getMethodId, req.getMethodId());

        IPage<TeachTextsEntity> pageResult = teachTextsService.page(page,lambdaQuery);

        // 转换为响应对象
        IPage<TeachTextsResp> respPage = pageResult.convert(AdminTeachTextConvert.INSTANCE::toTeachTextsResp);
        if (CollectionUtils.isEmpty(respPage.getRecords())) {
            return new Page<>(req.getPageNo(), req.getPageSize());
        }
        log.info("分页查询教学文本列表成功, 总数: {}", respPage.getTotal());
        Set<Integer> methodIds = respPage.getRecords().stream().map(TeachTextsResp::getMethodId).collect(Collectors.toSet());
        List<TeachMethodsEntity> teachMethodList = teachMethodsService.listByIds(methodIds);
        Map<Integer, String> methodMap = teachMethodList.stream().collect(Collectors.toMap(TeachMethodsEntity::getId, TeachMethodsEntity::getName, (a, b) -> a));
        for (TeachTextsResp resp : respPage.getRecords()) {
            if (Objects.nonNull(resp.getMethodId())) {
                resp.setMethodName(methodMap.get(resp.getMethodId()));
            }
        }
        return respPage;
    }

    @Override
    public TeachTextsResp getTeachTextById(Integer id) {
        log.info("根据ID查询教学文本详情, ID: {}", id);
        TeachTextsEntity entity = teachTextsService.getById(id);
        TeachTextsResp resp = AdminTeachTextConvert.INSTANCE.toTeachTextsResp(entity);
        if (Objects.nonNull(resp.getMethodId())) {
            TeachMethodsEntity method = teachMethodsService.getById(resp.getMethodId());
            if (Objects.nonNull(method)) {
                resp.setMethodName(method.getName());
            }
        }
        // 记录查看日志
        ModificationLogUtils.logModification(
                ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                id,
                "教学文本",
                ModificationLogEntity.OPERATION_TYPE_VIEW,
                StpUtil.getLoginIdAsInt(),
                "查看教学文本详情"
        );
        log.info("查询教学文本详情成功, ID: {}", id);
        return resp;
    }

    @Override
    public boolean addTeachText(TeachTextsReq req) {
        log.info("新增教学文本, 请求参数: {}", req);
        TeachTextsEntity entity = AdminTeachTextConvert.INSTANCE.toTeachTextsEntity(req);
        boolean result = teachTextsService.save(entity);

        if (result) {
            updateDefault(req.getGoalId(), req.getIsDefault(), entity.getId());

            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                    entity.getId(),
                    "教学文本",
                    ModificationLogEntity.OPERATION_TYPE_ADD,
                    null,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        log.info("新增教学文本结果: {}, ID: {}", result, entity.getId());
        return result;
    }

    @Override
    public boolean updateTeachText(Integer id, TeachTextsReq req) {
        log.info("更新教学文本, ID: {}, 请求参数: {}", id, req);
        // 获取修改前的数据
        TeachTextsEntity before = teachTextsService.getById(id);
        TeachTextsEntity entity = AdminTeachTextConvert.INSTANCE.toTeachTextsEntity(req);
        entity.setId(id);
        boolean result = teachTextsService.updateById(entity);

        // 记录修改日志
        if (result) {
            updateDefault(before.getGoalId(), req.getIsDefault(), id);

            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                    id,
                    "教学文本",
                    ModificationLogEntity.OPERATION_TYPE_UPDATE,
                    before,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        log.info("更新教学文本结果: {}", result);
        return result;
    }

    @Override
    public boolean updateTeachTextVideo(Integer id, TeachTextVideoUpdateReq req) {
        log.info("更新教学文本视频信息, ID: {}, 请求参数: {}", id, req);
        // 获取修改前的数据
        TeachTextsEntity before = teachTextsService.getById(id);

        TeachTextsEntity entity = new TeachTextsEntity();
        entity.setId(id);
        if (StringUtils.isNotBlank(req.getVideoContent())) {
            entity.setVideoContent(req.getVideoContent());
        }
        if (StringUtils.isNotBlank(req.getPythonScript())) {
            entity.setPythonScript(req.getPythonScript());
        }
        if (StringUtils.isNotBlank(req.getVideoUrl())) {
            entity.setVideoUrl(req.getVideoUrl());
        }
        boolean result = teachTextsService.updateById(entity);
        // 记录修改日志
        if (result) {
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                    id,
                    "教学文本",
                    ModificationLogEntity.OPERATION_TYPE_UPDATE,
                    before,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        log.info("更新教学文本视频信息结果: {}", result);
        return result;
    }


    private void updateDefault(Integer goalId, Integer defaultText, Integer id) {
        if (Objects.nonNull(defaultText) && CommonConstant.IS_DEFAULT.equals(defaultText)) {
            boolean updated = teachTextsService.update(new LambdaUpdateWrapper<>(TeachTextsEntity.class)
                    .set(TeachTextsEntity::getIsDefault, CommonConstant.IS_NOT_DEFAULT)
                    .eq(TeachTextsEntity::getGoalId, goalId)
                    .notIn(TeachTextsEntity::getId, id)
            );
            log.info("教学目标{}更新默认的讲课稿结果{}", goalId, updated ? "成功" : "失败");
        }
    }

    @Override
    public boolean deleteTeachText(Integer id) {
        log.info("删除教学文本, ID: {}", id);
        // 获取删除前的数据
        TeachTextsEntity before = teachTextsService.getById(id);
        boolean result = teachTextsService.removeById(id);

        // 记录删除日志
        if (result && before != null) {
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                    id,
                    "教学文本",
                    ModificationLogEntity.OPERATION_TYPE_DELETE,
                    before,
                    null,
                    StpUtil.getLoginIdAsInt()
            );
        }
        log.info("删除教学文本结果: {}", result);
        return result;
    }

    @Override
    public boolean updateTeachTextSort(Integer id, Integer sort) {
        log.info("更新教学文本的排序, ID: {}, 请求参数: {}", id, sort);
        // 获取修改前的数据
        TeachTextsEntity before = teachTextsService.getById(id);
        TeachTextsEntity entity = new TeachTextsEntity();
        entity.setId(id);
        entity.setSort(sort);
        boolean result = teachTextsService.updateById(entity);

        // 记录修改日志
        if (result) {
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_TEACH_TEXT,
                    id, "", ModificationLogEntity.OPERATION_TYPE_UPDATE, StpUtil.getLoginIdAsInt(), "更新教学文本的排序"
            );
        }
        return result;
    }

    @Override
    public String uploadTeachVideoAndUpdateUrl(Integer textId, MultipartFile videoFile) {
        try {
            if (videoFile.isEmpty()) {
                log.error("上传文件为空");
                return "";
            }
            // 获取文件原始名称
            String originalFilename = videoFile.getOriginalFilename();

            String contentType = videoFile.getContentType();
            String url = commonFileService.upload(videoFile.getInputStream(), videoUploadBucketName, "video", originalFilename, contentType);
            log.info("上传文件成功, 文件名: {}, 文件路径: {}", originalFilename, url);
            if (StringUtils.isNotBlank(url)) {
                TeachTextsEntity entity = new TeachTextsEntity();
                entity.setId(textId);
                entity.setVideoUrl(url);
                teachTextsService.updateById(entity);
            }
            return url;
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return "";
        }
    }
    
    @Override
    public void downloadTeachVideo(Integer textId, HttpServletResponse response) {
        InputStream inputStream = null;
        try {
            // 获取教学文本信息
            TeachTextsEntity teachText = teachTextsService.getById(textId);
            if (teachText == null) {
                log.error("未找到ID为{}的教学文本", textId);
                response.sendError(HttpServletResponse.SC_NOT_FOUND, "未找到指定的教学文本");
                return;
            }
            
            // 获取视频URL
            String videoUrl = teachText.getVideoUrl();
            if (StringUtils.isBlank(videoUrl)) {
                log.error("教学文本(ID:{})未关联视频", textId);
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "该教学文本未关联视频文件");
                return;
            }
            
            String fileName = extractFileNameFromUrl(videoUrl);

            // 从存储服务下载文件
            inputStream = commonFileService.downloadFileFromUrl(videoUploadBucketName, videoUrl);
            
            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + 
                URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20") + "\"");
            
            // 将文件内容写入响应流
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
            }
            response.getOutputStream().flush();
            log.info("成功下载教学视频，教学文本ID: {}, 文件名: {}", textId, fileName);
        } catch (Exception e) {
            log.error("下载教学视频失败，教学文本ID: {}", textId, e);
            try {
                if (!response.isCommitted()) {
                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "下载视频文件失败: " + e.getMessage());
                }
            } catch (Exception ex) {
                log.error("发送错误响应失败", ex);
            }
        } finally {
            // 确保输入流被正确关闭
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭输入流失败", e);
                }
            }
        }
    }
    
    /**
     * 从URL中提取文件名
     * @param url 完整的文件URL
     * @return 文件名
     */
    private String extractFileNameFromUrl(String url) {
        try {
            // 从URL最后部分提取文件名
            String[] parts = url.split("/");
            return parts[parts.length - 1];
        } catch (Exception e) {
            log.warn("解析文件名失败，使用默认名称: video.mp4");
            return "video.mp4";
        }
    }
}