package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.StoreOfficialAlbum;
import shop.alien.entity.store.StoreVideo;
import shop.alien.entity.store.dto.StoreVideoSaveDto;
import shop.alien.mapper.StoreOfficialAlbumMapper;
import shop.alien.mapper.StoreVideoMapper;
import shop.alien.store.service.StoreVideoService;
import shop.alien.store.util.CommonConstant;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.RandomCreateUtil;
import shop.alien.util.common.VideoUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;

/**
 * 门店视频 服务实现类
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Transactional
@Service
@RequiredArgsConstructor
public class StoreVideoServiceImpl extends ServiceImpl<StoreVideoMapper, StoreVideo> implements StoreVideoService {

    private final VideoUtils videoUtils;

    private final AliOSSUtil aliOSSUtil;

    private final StoreOfficialAlbumMapper storeOfficialAlbumMapper;

    /**
     * 视频文件类型列表
     */
    private static final List<String> VIDEO_FILE_TYPES = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");

    @Value("${spring.web.resources.static-locations}")
    private String uploadDir;

    /**
     * 保存视频（单个或批量）
     *
     * @param dto 视频保存DTO，包含门店ID、相册ID和视频URL列表
     * @return 是否保存成功
     */
    @Override
    public boolean saveOrSaveBatch(StoreVideoSaveDto dto) {
        // 参数验证
        if (dto == null) {
            log.error("StoreVideoServiceImpl.saveOrSaveBatch ERROR: dto is null");
            return false;
        }
        if (dto.getStoreId() == null || dto.getStoreId() <= 0) {
            log.error("StoreVideoServiceImpl.saveOrSaveBatch ERROR: storeId is invalid");
            return false;
        }
        if (dto.getVideoUrls() == null || dto.getVideoUrls().isEmpty()) {
            log.error("StoreVideoServiceImpl.saveOrSaveBatch ERROR: videoUrls is empty");
            return false;
        }

        // 解析视频URL列表，前端只传入视频URL，后端自动匹配或生成封面
        // 排序号将根据传入数组的顺序设置（从1开始），用于支持编辑排序功能
        List<StoreVideo> videoList = new java.util.ArrayList<>();
        List<String> videoUrls = dto.getVideoUrls();
        List<Integer> videoIds = dto.getVideoIds(); // 可选的视频ID列表，用于编辑
        List<String> coverUrls = dto.getCoverUrls();

        // 遍历URL列表，每个URL都是视频URL
        int videoIndex = 0;
        for (int i = 0; i < videoUrls.size(); i++) {
            String videoUrl = videoUrls.get(i);
            if (StringUtils.isBlank(videoUrl)) {
                log.warn("视频URL为空，跳过该视频");
                continue;
            }
            
            // 获取对应的视频ID（如果存在）
            Integer videoId = null;
            if (videoIds != null && i < videoIds.size()) {
                videoId = videoIds.get(i);
            }
            
            // 如果ID存在且有效，尝试查询现有视频进行更新
            StoreVideo storeVideo = null;
            if (videoId != null && videoId > 0) {
                try {
                    storeVideo = this.getById(videoId);
                    if (storeVideo != null && storeVideo.getDeleteFlag() == CommonConstant.DELETE_FLAG_UNDELETE) {
                        log.info("找到现有视频，ID：{}，将进行更新，排序号将根据数组顺序设置为：{}", videoId, videoIndex + 1);
                    } else {
                        log.warn("视频ID：{} 不存在或已删除，将作为新增处理", videoId);
                        storeVideo = null;
                    }
                } catch (Exception e) {
                    log.error("查询视频失败，ID：{}，错误：{}，将作为新增处理", videoId, e.getMessage());
                    storeVideo = null;
                }
            }
            
            // 如果不存在现有视频，创建新对象
            if (storeVideo == null) {
                storeVideo = new StoreVideo();
                storeVideo.setId(null); // 确保ID为null，表示新增
                // 新增时，根据数组顺序设置排序号（从1开始）
                storeVideo.setImgSort(videoIndex + 1);
                storeVideo.setImgDescription("相册视频");
            } else {
                // 更新时，根据数组顺序更新排序号（从1开始）
                // 这样可以根据传入的数组顺序来调整视频的排序
                storeVideo.setImgSort(videoIndex + 1);
                // 更新时，如果描述未设置，使用默认值
                if (StringUtils.isBlank(storeVideo.getImgDescription())) {
                    storeVideo.setImgDescription("相册视频");
                }
            }
            
            // 设置基本信息
            storeVideo.setStoreId(dto.getStoreId());
            storeVideo.setBusinessId(dto.getBusinessId());
            
            // 尝试根据视频URL自动匹配封面URL（从/file/uploadMore接口获取的封面URL格式）
            // 封面URL格式：视频URL的扩展名从.mp4等替换为.jpg
//            String coverUrl = tryMatchCoverUrl(videoUrl);
//
//            // 如果匹配不到封面URL，尝试处理视频生成封面
//            if (StringUtils.isBlank(coverUrl)) {
//                log.info("未找到匹配的封面URL，视频URL：{}，将尝试处理生成封面", videoUrl);
//                try {
//                    // 调用processVideoAndCover处理，生成封面
//                    String processedImgUrl = processVideoAndCover(videoUrl);
//                    if (StringUtils.isNotBlank(processedImgUrl)) {
//                        // 如果处理成功，processedImgUrl已经是JSON格式，直接使用
//                        storeVideo.setImgUrl(processedImgUrl);
//                        videoList.add(storeVideo);
//                        videoIndex++;
//                        continue;
//                    }
//                } catch (Exception e) {
//                    log.error("处理视频封面失败，视频URL：{}，错误：{}，将保存视频但不包含封面", videoUrl, e.getMessage(), e);
//                    // 处理失败时，继续执行下面的逻辑，保存视频但不包含封面
//                }
//            }
            
            // 组合成JSON对象格式（即使没有封面也保存）
            JSONObject videoJson = new JSONObject();
            videoJson.put("video", videoUrl);
            String coverUrl = coverUrls.get(i);
//            if (StringUtils.isBlank(coverUrl)) {
                videoJson.put("cover", coverUrl);
//            }
            
            storeVideo.setImgUrl(JSON.toJSONString(videoJson));
            
            videoList.add(storeVideo);
            videoIndex++;
        }

        // 批量保存或更新
        if (videoList.isEmpty()) {
            log.warn("没有有效的视频数据需要保存");
            return false;
        }

        boolean saveResult;
        // 分离新增和更新的视频
        List<StoreVideo> insertList = new java.util.ArrayList<>();
        List<StoreVideo> updateList = new java.util.ArrayList<>();
        
        for (StoreVideo video : videoList) {
            if (video.getId() != null && video.getId() > 0) {
                updateList.add(video);
            } else {
                insertList.add(video);
            }
        }
        
        // 执行新增和更新
        try {
            if (!insertList.isEmpty()) {
                if (insertList.size() == 1) {
                    saveResult = super.save(insertList.get(0));
                } else {
                    saveResult = super.saveBatch(insertList);
                }
                log.info("新增视频数量：{}", insertList.size());
            } else {
                saveResult = true; // 如果没有新增，默认成功
            }
            
            if (!updateList.isEmpty()) {
                boolean updateResult;
                if (updateList.size() == 1) {
                    updateResult = super.updateById(updateList.get(0));
                } else {
                    updateResult = super.updateBatchById(updateList);
                }
                saveResult = saveResult && updateResult;
                log.info("更新视频数量：{}", updateList.size());
            }
        } catch (Exception e) {
            log.error("保存或更新视频失败，错误：{}", e.getMessage(), e);
            return false;
        }

        // 保存成功后，更新相册的imgCount
        if (saveResult && dto.getBusinessId() != null && dto.getBusinessId() > 0) {
            try {
                updateAlbumImgCount(dto.getBusinessId());
            } catch (Exception e) {
                log.error("更新相册imgCount失败，相册ID：{}，错误：{}", dto.getBusinessId(), e.getMessage(), e);
                // 不影响保存结果，只记录错误日志
            }
        }

        return saveResult;
    }

    /**
     * 更新相册的imgCount（统计该相册下的视频数量）
     *
     * @param albumId 相册ID
     */
    private void updateAlbumImgCount(Integer albumId) {
        try {
            // 统计该相册下的视频数量
            LambdaQueryWrapper<StoreVideo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StoreVideo::getBusinessId, albumId)
                    .eq(StoreVideo::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);
            long videoCount = this.count(queryWrapper);

            // 更新相册的imgCount
            LambdaUpdateWrapper<StoreOfficialAlbum> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(StoreOfficialAlbum::getId, albumId)
                    .set(StoreOfficialAlbum::getImgCount, (int) videoCount);
            storeOfficialAlbumMapper.update(null, updateWrapper);

            log.info("更新相册imgCount成功，相册ID：{}，视频数量：{}", albumId, videoCount);
        } catch (Exception e) {
            log.error("更新相册imgCount失败，相册ID：{}，错误：{}", albumId, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 处理视频URL，截取第一帧作为封面并生成JSON对象
     * 只支持JSON对象格式：{"video": "...", "cover": "..."}
     *
     * @param imgUrl 视频URL或JSON对象字符串
     * @return 处理后的JSON对象字符串，格式：{"video": "...", "cover": "..."}
     */
    private String processVideoAndCover(String imgUrl) {
        log.info("StoreVideoServiceImpl.processVideoAndCover imgUrl={}", imgUrl);
        
        // 参数验证
        if (StringUtils.isBlank(imgUrl)) {
            log.warn("StoreVideoServiceImpl.processVideoAndCover imgUrl is blank");
            return imgUrl;
        }

        String videoUrl = null;
        String coverUrl = null;

        // 判断imgUrl是否为JSON对象格式
        try {
            JSONObject jsonObject = JSON.parseObject(imgUrl);
            if (jsonObject != null && jsonObject.containsKey("video")) {
                videoUrl = jsonObject.getString("video");
                coverUrl = jsonObject.getString("cover");
                // 如果已经有cover，则直接返回
                if (StringUtils.isNotBlank(coverUrl)) {
                    log.info("StoreVideoServiceImpl.processVideoAndCover 已有封面，无需重新生成");
                    return imgUrl;
                }
            }
        } catch (Exception e) {
            // 如果不是JSON格式，则将imgUrl视为视频URL
            log.debug("StoreVideoServiceImpl.processVideoAndCover imgUrl不是JSON格式，视为视频URL");
            videoUrl = imgUrl;
        }

        // 如果videoUrl为空，无法处理
        if (StringUtils.isBlank(videoUrl)) {
            log.warn("StoreVideoServiceImpl.processVideoAndCover videoUrl is blank");
            return imgUrl;
        }

        // 检查是否为视频URL
        if (!isVideoUrl(videoUrl)) {
            log.warn("StoreVideoServiceImpl.processVideoAndCover 不是视频URL: {}", videoUrl);
            return imgUrl;
        }

        // 下载视频并截取封面
        File tempVideoFile = null;
        File coverFile = null;
        try {
            // 从URL下载视频到临时文件
            tempVideoFile = downloadVideoFromUrl(videoUrl);
            if (tempVideoFile == null || !tempVideoFile.exists()) {
                log.error("StoreVideoServiceImpl.processVideoAndCover 下载视频失败: {}", videoUrl);
                return imgUrl;
            }

            // 截取第一帧作为封面
            String coverPath = videoUtils.getFirstFrame(tempVideoFile.getAbsolutePath());
            if (StringUtils.isBlank(coverPath)) {
                log.error("StoreVideoServiceImpl.processVideoAndCover 截取封面失败: {}", tempVideoFile.getAbsolutePath());
                return imgUrl;
            }

            coverFile = new File(coverPath);
            if (!coverFile.exists()) {
                log.error("StoreVideoServiceImpl.processVideoAndCover 封面文件不存在: {}", coverPath);
                return imgUrl;
            }

            // 上传封面到OSS
            String coverFileName = generateCoverFileName(videoUrl);
            String coverOssPath = "video/" + coverFileName + ".jpg";
            coverUrl = aliOSSUtil.uploadFile(coverFile, coverOssPath);
            if (StringUtils.isBlank(coverUrl)) {
                log.error("StoreVideoServiceImpl.processVideoAndCover 上传封面失败: {}", coverOssPath);
                return imgUrl;
            }

            // 构建JSON对象（格式：{"video": "...", "cover": "..."}）
            JSONObject resultObject = new JSONObject();
            resultObject.put("video", videoUrl);
            resultObject.put("cover", coverUrl);

            log.info("StoreVideoServiceImpl.processVideoAndCover 处理成功, videoUrl: {}, coverUrl: {}", videoUrl, coverUrl);
            return JSON.toJSONString(resultObject);

        } catch (Exception e) {
            log.error("StoreVideoServiceImpl.processVideoAndCover 处理异常", e);
            return imgUrl;
        } finally {
            // 清理临时文件
            if (tempVideoFile != null && tempVideoFile.exists()) {
                boolean deleted = tempVideoFile.delete();
                if (!deleted) {
                    log.warn("StoreVideoServiceImpl.processVideoAndCover 删除临时视频文件失败: {}", tempVideoFile.getAbsolutePath());
                }
            }
            if (coverFile != null && coverFile.exists()) {
                boolean deleted = coverFile.delete();
                if (!deleted) {
                    log.warn("StoreVideoServiceImpl.processVideoAndCover 删除临时封面文件失败: {}", coverFile.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 检查URL是否为视频URL
     *
     * @param url 视频URL
     * @return 是否为视频URL
     */
    private boolean isVideoUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return false;
        }
        // 检查URL是否以视频文件扩展名结尾
        String lowerUrl = url.toLowerCase();
        for (String videoType : VIDEO_FILE_TYPES) {
            if (lowerUrl.endsWith("." + videoType)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 从URL下载视频到临时文件
     *
     * @param videoUrl 视频URL
     * @return 临时文件对象
     */
    private File downloadVideoFromUrl(String videoUrl) {
        log.info("StoreVideoServiceImpl.downloadVideoFromUrl videoUrl={}", videoUrl);
        
        InputStream inputStream = null;
        FileOutputStream outputStream = null;
        File tempFile = null;
        
        try {
            // 创建URL连接
            URL url = new URL(videoUrl);
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(10000); // 10秒连接超时
            connection.setReadTimeout(60000); // 60秒读取超时

            // 创建临时文件
            String tempDir = uploadDir.endsWith("/") ? uploadDir : uploadDir + "/";
            String tempFileName = "temp_video_" + System.currentTimeMillis() + "_" + RandomCreateUtil.getRandomNum(6);
            
            // 从URL中提取文件扩展名
            String fileExtension = getFileExtensionFromUrl(videoUrl);
            if (StringUtils.isNotBlank(fileExtension)) {
                tempFileName += "." + fileExtension;
            } else {
                tempFileName += ".mp4"; // 默认使用mp4扩展名
            }
            
            tempFile = new File(tempDir + tempFileName);
            
            // 确保目录存在
            File parentDir = tempFile.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

            // 下载文件
            inputStream = connection.getInputStream();
            outputStream = new FileOutputStream(tempFile);
            
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();

            log.info("StoreVideoServiceImpl.downloadVideoFromUrl 下载成功, tempFile: {}", tempFile.getAbsolutePath());
            return tempFile;

        } catch (Exception e) {
            log.error("StoreVideoServiceImpl.downloadVideoFromUrl 下载失败, videoUrl: {}", videoUrl, e);
            // 如果下载失败，删除可能创建的临时文件
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
            return null;
        } finally {
            // 关闭流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e) {
                    log.warn("StoreVideoServiceImpl.downloadVideoFromUrl 关闭输入流失败", e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    log.warn("StoreVideoServiceImpl.downloadVideoFromUrl 关闭输出流失败", e);
                }
            }
        }
    }

    /**
     * 从URL中提取文件扩展名
     *
     * @param url 文件URL
     * @return 文件扩展名（不包含点）
     */
    private String getFileExtensionFromUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return null;
        }
        
        // 移除URL参数
        int questionMarkIndex = url.indexOf('?');
        if (questionMarkIndex > 0) {
            url = url.substring(0, questionMarkIndex);
        }
        
        // 提取扩展名
        int lastDotIndex = url.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < url.length() - 1) {
            return url.substring(lastDotIndex + 1).toLowerCase();
        }
        
        return null;
    }

    /**
     * 生成封面文件名
     *
     * @param videoUrl 视频URL
     * @return 封面文件名（不包含扩展名）
     */
    private String generateCoverFileName(String videoUrl) {
        // 从视频URL中提取文件名（去除扩展名）
        String fileName = "cover_" + System.currentTimeMillis() + "_" + RandomCreateUtil.getRandomNum(6);
        
        try {
            // 尝试从URL中提取原始文件名
            String urlPath = new URL(videoUrl).getPath();
            int lastSlashIndex = urlPath.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < urlPath.length() - 1) {
                String originalFileName = urlPath.substring(lastSlashIndex + 1);
                // 移除文件扩展名
                int lastDotIndex = originalFileName.lastIndexOf('.');
                if (lastDotIndex > 0) {
                    String nameWithoutExt = originalFileName.substring(0, lastDotIndex);
                    // 清理文件名，移除特殊字符
                    nameWithoutExt = nameWithoutExt.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5]", "");
                    if (StringUtils.isNotBlank(nameWithoutExt)) {
                        fileName = nameWithoutExt + RandomCreateUtil.getRandomNum(6);
                    }
                }
            }
        } catch (Exception e) {
            log.debug("StoreVideoServiceImpl.generateCoverFileName 从URL提取文件名失败", e);
        }
        
        // 清理文件名，避免包含逗号等特殊字符
        fileName = fileName.replaceAll(",", "");
        
        return fileName;
    }

    /**
     * 根据门店ID获取视频列表
     *
     * @param storeId 门店id
     * @return 视频列表
     */
    @Override
    public List<StoreVideo> getByStoreId(Integer storeId) {
        LambdaQueryWrapper<StoreVideo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreVideo::getStoreId, storeId)
                .orderByAsc(StoreVideo::getImgSort);
        return this.list(lambdaQueryWrapper);
    }

    /**
     * 根据门店ID和业务ID获取视频列表
     *
     * @param storeId 门店id
     * @param businessId 业务ID
     * @return 视频列表
     */
    @Override
    public List<StoreVideo> getByStoreIdAndBusinessId(Integer storeId, Integer businessId) {
        LambdaQueryWrapper<StoreVideo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreVideo::getStoreId, storeId)
                .eq(StoreVideo::getBusinessId, businessId)
                .orderByAsc(StoreVideo::getImgSort);
        return this.list(lambdaQueryWrapper);
    }

    /**
     * 尝试根据视频URL匹配封面URL
     * 从/file/uploadMore接口获取的封面URL格式：视频URL的扩展名从.mp4等替换为.jpg
     *
     * @param videoUrl 视频URL
     * @return 封面URL，如果匹配不到则返回null
     */
    private String tryMatchCoverUrl(String videoUrl) {
        if (StringUtils.isBlank(videoUrl)) {
            return null;
        }
        
        try {
            // 检查是否为视频URL
            if (!isVideoUrl(videoUrl)) {
                return null;
            }
            
            // 提取视频文件名（不含扩展名）
            int lastDotIndex = videoUrl.lastIndexOf('.');
            int lastSlashIndex = Math.max(videoUrl.lastIndexOf('/'), videoUrl.lastIndexOf('\\'));
            
            if (lastDotIndex > lastSlashIndex && lastDotIndex > 0) {
                // 构建封面URL：将扩展名替换为.jpg
                String coverUrl = videoUrl.substring(0, lastDotIndex) + ".jpg";
                log.debug("尝试匹配封面URL，视频URL：{}，封面URL：{}", videoUrl, coverUrl);
                return coverUrl;
            }
        } catch (Exception e) {
            log.debug("匹配封面URL失败，视频URL：{}，错误：{}", videoUrl, e.getMessage());
        }
        
        return null;
    }

}

