package com.example.demo.service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.example.demo.model.ImageToVideoTask;
import com.example.demo.model.StoryboardVideoTask;
import com.example.demo.model.TextToVideoTask;
import com.example.demo.model.User;
import com.example.demo.model.UserWork;
import com.example.demo.model.enums.CommonTaskType;
import com.example.demo.repository.ImageToVideoTaskRepository;
import com.example.demo.repository.StoryboardVideoTaskRepository;
import com.example.demo.repository.TextToVideoTaskRepository;
import com.example.demo.repository.UserWorkRepository;

/**
 * 用户作品服务类
 */
@Service
@Transactional
public class UserWorkService {

    private static final Logger logger = LoggerFactory.getLogger(UserWorkService.class);

    @Autowired
    private UserWorkRepository userWorkRepository;

    @Autowired
    private TextToVideoTaskRepository textToVideoTaskRepository;

    @Autowired
    private UserService userService;

    @Autowired
    private ImageToVideoTaskRepository imageToVideoTaskRepository;

    @Autowired
    private StoryboardVideoTaskRepository storyboardVideoTaskRepository;

    // 每个用户最多同时执行的任务数
    private static final int MAX_CONCURRENT_TASKS = 3;

    /**
     * 检查用户是否可以创建新任务
     * @param username 用户名
     * @throws IllegalStateException 如果用户已达到最大并发任务数
     */
    @Transactional(readOnly = true)
    public void checkMaxConcurrentTasks(String username) {
        long processingCount = userWorkRepository.countProcessingTasksByUsername(username);
        if (processingCount >= MAX_CONCURRENT_TASKS) {
            throw new IllegalStateException("您当前有 " + processingCount + " 个任务正在执行，最多同时执行 " + MAX_CONCURRENT_TASKS + " 个任务，请等待部分任务完成后再提交");
        }
        logger.info("用户 {} 当前进行中任务数: {}/{}", username, processingCount, MAX_CONCURRENT_TASKS);
    }

    /**
     * 获取用户当前进行中的任务数量
     */
    @Transactional(readOnly = true)
    public long getProcessingTaskCount(String username) {
        return userWorkRepository.countProcessingTasksByUsername(username);
    }

    /**
     * 从任务创建作品
     * 使用 REQUIRES_NEW 传播行为，防止内部异常导致外部事务回滚
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public UserWork createWorkFromTask(String taskId, String resultUrl) {
        // 检查是否已存在作品（使用同步检查，防止并发创建）
        // 注意：这个检查不是原子的，但配合外部的悲观锁应该能防止大部分并发问题
        Optional<UserWork> existingWork = userWorkRepository.findByTaskId(taskId);
        if (existingWork.isPresent()) {
            logger.info("作品已存在，更新resultUrl: taskId={}, workId={}", taskId, existingWork.get().getId());
            UserWork work = existingWork.get();
            work.setResultUrl(resultUrl);
            work.setStatus(UserWork.WorkStatus.COMPLETED);
            work.setCompletedAt(LocalDateTime.now());
            return userWorkRepository.save(work);
        }

        try {
            // 尝试从文生视频任务创建作品
            Optional<TextToVideoTask> textTaskOpt = textToVideoTaskRepository.findByTaskId(taskId);
            if (textTaskOpt.isPresent()) {
                TextToVideoTask task = textTaskOpt.get();
                return createTextToVideoWork(task, resultUrl);
            }

            // 尝试从图生视频任务创建作品
            Optional<ImageToVideoTask> imageTaskOpt = imageToVideoTaskRepository.findByTaskId(taskId);
            if (imageTaskOpt.isPresent()) {
                ImageToVideoTask task = imageTaskOpt.get();
                return createImageToVideoWork(task, resultUrl);
            }

            // 尝试从分镜视频任务创建作品
            Optional<StoryboardVideoTask> storyboardTaskOpt = storyboardVideoTaskRepository.findByTaskId(taskId);
            if (storyboardTaskOpt.isPresent()) {
                StoryboardVideoTask task = storyboardTaskOpt.get();
                return createStoryboardVideoWork(task, resultUrl);
            }

            throw new RuntimeException("找不到对应的任务: " + taskId);
        } catch (org.springframework.dao.DataIntegrityViolationException e) {
            // 捕获数据库唯一约束违反异常（如果task_id有唯一约束）
            // 或者捕获其他数据完整性异常
            if (e.getMessage() != null && e.getMessage().contains("Duplicate entry")) {
                logger.warn("作品可能已存在（数据库约束冲突），重新查询: {}", taskId);
                // 重新查询，可能其他线程已经创建了
                Optional<UserWork> retryWork = userWorkRepository.findByTaskId(taskId);
                if (retryWork.isPresent()) {
                    return retryWork.get();
                }
            }
            throw e;
        }
    }

    /**
     * 创建PROCESSING状态的文生视频作品（任务开始时调用）
     */
    public UserWork createProcessingTextToVideoWork(TextToVideoTask task) {
        // 检查是否已存在
        Optional<UserWork> existing = userWorkRepository.findByTaskId(task.getTaskId());
        if (existing.isPresent()) {
            logger.info("作品已存在，跳过创建: taskId={}", task.getTaskId());
            return existing.get();
        }
        
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.TEXT_TO_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("文生视频作品");
        work.setPrompt(task.getPrompt());
        work.setDuration(String.valueOf(task.getDuration()) + "s");
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(task.isHdMode() ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());  // 设置预估积分成本
        work.setStatus(UserWork.WorkStatus.PROCESSING);  // 初始状态为PROCESSING
        
        work = userWorkRepository.save(work);
        logger.info("创建PROCESSING状态文生视频作品: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }
    
    /**
     * 创建文生视频作品
     */
    private UserWork createTextToVideoWork(TextToVideoTask task, String resultUrl) {
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.TEXT_TO_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("文生视频作品");
        work.setPrompt(task.getPrompt());
        work.setResultUrl(resultUrl);
        work.setDuration(String.valueOf(task.getDuration()) + "s");
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(task.isHdMode() ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());
        work.setStatus(UserWork.WorkStatus.COMPLETED);
        work.setCompletedAt(LocalDateTime.now());

        work = userWorkRepository.save(work);
        logger.info("创建文生视频作品成功: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }

    /**
     * 创建PROCESSING状态的图生视频作品（任务开始时调用）
     */
    public UserWork createProcessingImageToVideoWork(ImageToVideoTask task) {
        // 检查是否已存在
        Optional<UserWork> existing = userWorkRepository.findByTaskId(task.getTaskId());
        if (existing.isPresent()) {
            logger.info("作品已存在，跳过创建: taskId={}", task.getTaskId());
            return existing.get();
        }
        
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.IMAGE_TO_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("图生视频作品");
        work.setPrompt(task.getPrompt());
        work.setDuration(String.valueOf(task.getDuration()) + "s");
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(Boolean.TRUE.equals(task.getHdMode()) ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());  // 设置预估积分成本
        work.setStatus(UserWork.WorkStatus.PROCESSING);  // 初始状态为PROCESSING
        work.setThumbnailUrl(task.getFirstFrameUrl());  // 保存首帧图片URL用于恢复时显示
        
        work = userWorkRepository.save(work);
        logger.info("创建PROCESSING状态图生视频作品: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }
    
    /**
     * 创建图生视频作品
     */
    private UserWork createImageToVideoWork(ImageToVideoTask task, String resultUrl) {
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.IMAGE_TO_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("图生视频作品");
        work.setPrompt(task.getPrompt());
        work.setResultUrl(resultUrl);
        work.setDuration(String.valueOf(task.getDuration()) + "s");
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(Boolean.TRUE.equals(task.getHdMode()) ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());
        work.setStatus(UserWork.WorkStatus.COMPLETED);
        work.setCompletedAt(LocalDateTime.now());

        work = userWorkRepository.save(work);
        logger.info("创建图生视频作品成功: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }

    /**
     * 创建PROCESSING状态的分镜视频作品（任务开始时调用）
     */
    public UserWork createProcessingStoryboardVideoWork(StoryboardVideoTask task) {
        // 检查是否已存在
        Optional<UserWork> existing = userWorkRepository.findByTaskId(task.getTaskId());
        if (existing.isPresent()) {
            logger.info("作品已存在，跳过创建: taskId={}", task.getTaskId());
            return existing.get();
        }
        
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.STORYBOARD_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("分镜视频作品");
        work.setPrompt(task.getPrompt());
        work.setDuration("10s");  // 分镜视频默认10秒
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(task.isHdMode() ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());  // 设置预估积分成本
        work.setStatus(UserWork.WorkStatus.PROCESSING);  // 初始状态为PROCESSING
        work.setThumbnailUrl(task.getImageUrl());  // 保存参考图URL用于恢复时显示
        
        work = userWorkRepository.save(work);
        logger.info("创建PROCESSING状态分镜视频作品: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }
    
    /**
     * 创建分镜视频作品
     */
    private UserWork createStoryboardVideoWork(StoryboardVideoTask task, String resultUrl) {
        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(task.getTaskId());
        work.setWorkType(CommonTaskType.STORYBOARD_VIDEO);
        work.setTitle(generateTitle(task.getPrompt()));
        work.setDescription("分镜视频作品");
        // 优先使用 videoPrompt，如果没有则使用原始 prompt
        String displayPrompt = task.getVideoPrompt();
        if (displayPrompt == null || displayPrompt.trim().isEmpty()) {
            displayPrompt = task.getPrompt();
        }
        work.setPrompt(displayPrompt);
        work.setResultUrl(resultUrl);
        work.setThumbnailUrl(task.getResultUrl()); // 保存分镜图作为缩略图
        work.setImagePrompt(task.getImagePrompt()); // 保存优化后的分镜图提示词
        work.setVideoPrompt(task.getVideoPrompt()); // 保存优化后的视频提示词
        work.setDuration(task.getDuration() != null ? task.getDuration() + "s" : "10s");
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(task.isHdMode() ? "HD" : "SD");
        work.setPointsCost(task.getCostPoints());
        work.setStatus(UserWork.WorkStatus.COMPLETED);
        work.setCompletedAt(LocalDateTime.now());
        work.setUploadedImages(task.getUploadedImages()); // 同步分镜图阶段用户上传的参考图
        work.setVideoReferenceImages(task.getVideoReferenceImages()); // 同步视频阶段用户上传的参考图，用于"做同款"

        work = userWorkRepository.save(work);
        logger.info("创建分镜视频作品成功: {}, 用户: {}, 分镜图: {}", work.getId(), work.getUsername(), task.getResultUrl() != null ? "有" : "无");
        return work;
    }

    /**
     * 创建分镜图作品（从分镜视频任务的分镜图阶段）
     */
    @Transactional
    public UserWork createStoryboardImageWork(String taskId, String imageUrl) {
        // 检查是否已存在分镜图作品（避免重复创建）
        Optional<UserWork> existingWork = userWorkRepository.findByTaskId(taskId + "_image");
        if (existingWork.isPresent()) {
            logger.info("分镜图作品已存在，跳过创建: taskId={}, workId={}", taskId, existingWork.get().getId());
            return existingWork.get();
        }

        // 获取分镜视频任务
        Optional<StoryboardVideoTask> taskOpt = storyboardVideoTaskRepository.findByTaskId(taskId);
        if (!taskOpt.isPresent()) {
            throw new RuntimeException("找不到分镜视频任务: " + taskId);
        }

        StoryboardVideoTask task = taskOpt.get();

        UserWork work = new UserWork();
        work.setUserId(getUserIdByUsername(task.getUsername()));
        work.setUsername(task.getUsername());
        work.setTaskId(taskId + "_image"); // 添加后缀区分分镜图和视频
        work.setWorkType(CommonTaskType.STORYBOARD_IMAGE);
        work.setTitle(generateTitle(task.getPrompt()) + " - 分镜图");
        work.setDescription("分镜图作品");
        work.setPrompt(task.getPrompt());
        work.setResultUrl(imageUrl);
        work.setAspectRatio(task.getAspectRatio());
        work.setQuality(task.isHdMode() ? "HD" : "SD");
        work.setPointsCost(0); // 分镜图不单独扣费
        work.setStatus(UserWork.WorkStatus.COMPLETED);
        work.setCompletedAt(LocalDateTime.now());
        work.setUploadedImages(task.getUploadedImages()); // 同步用户上传的参考图，用于"做同款"

        work = userWorkRepository.save(work);
        logger.info("创建分镜图作品成功: {}, 用户: {}", work.getId(), work.getUsername());
        return work;
    }

    /**
     * 更新分镜视频作品状态为分镜图完成
     * 分镜图生成完成后调用，将 PROCESSING 状态改为 COMPLETED
     * 这样主页不会显示"生成中"的轮询状态
     */
    @Transactional
    public void updateStoryboardVideoWorkToImageCompleted(String taskId, String imageUrl) {
        Optional<UserWork> workOpt = userWorkRepository.findByTaskId(taskId);
        if (workOpt.isPresent()) {
            UserWork work = workOpt.get();
            // 只更新 PROCESSING 状态的分镜视频作品
            if (work.getWorkType() == CommonTaskType.STORYBOARD_VIDEO 
                && work.getStatus() == UserWork.WorkStatus.PROCESSING) {
                work.setStatus(UserWork.WorkStatus.COMPLETED);
                work.setResultUrl(imageUrl); // 暂时设置为分镜图URL
                work.setThumbnailUrl(imageUrl);
                work.setCompletedAt(LocalDateTime.now());
                userWorkRepository.save(work);
                logger.info("分镜视频作品状态已更新为分镜图完成: taskId={}, workId={}", taskId, work.getId());
            }
        } else {
            logger.warn("未找到分镜视频作品记录: taskId={}", taskId);
        }
    }

    /**
     * 更新分镜视频作品状态为视频生成中
     * 用户点击"生成视频"后调用，将 COMPLETED 状态改回 PROCESSING
     */
    @Transactional
    public void updateStoryboardVideoWorkToProcessing(String taskId) {
        Optional<UserWork> workOpt = userWorkRepository.findByTaskId(taskId);
        if (workOpt.isPresent()) {
            UserWork work = workOpt.get();
            // 只更新分镜视频作品
            if (work.getWorkType() == CommonTaskType.STORYBOARD_VIDEO) {
                work.setStatus(UserWork.WorkStatus.PROCESSING);
                work.setCompletedAt(null); // 清除完成时间
                userWorkRepository.save(work);
                logger.info("分镜视频作品状态已更新为视频生成中: taskId={}, workId={}", taskId, work.getId());
            }
        } else {
            logger.warn("未找到分镜视频作品记录: taskId={}", taskId);
        }
    }

    /**
     * 根据用户名获取用户ID
     */
    private Long getUserIdByUsername(String username) {
        try {
            User user = userService.findByUsername(username);
            if (user != null) {
                return user.getId();
            }
            logger.warn("找不到用户: {}", username);
            return null;
        } catch (Exception e) {
            logger.error("获取用户ID失败: {}", username, e);
            return null;
        }
    }

    /**
     * 生成作品标题
     */
    private String generateTitle(String prompt) {
        if (prompt == null || prompt.trim().isEmpty()) {
            return "未命名作品";
        }
        
        // 取提示词的前20个字符作为标题
        String title = prompt.trim();
        if (title.length() > 20) {
            title = title.substring(0, 20) + "...";
        }
        return title;
    }

    /**
     * 获取用户作品列表（只返回有resultUrl的作品）
     * 用于创作页面历史记录，过滤掉没有resultUrl的作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getUserWorks(String username, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findByUsernameWithResultUrlOrderByCreatedAtDesc(username, pageable);
    }
    
    /**
     * 获取用户的所有作品列表（分页），包括正在排队和生成中的作品
     * 用于"我的作品"页面，显示所有状态的作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getAllUserWorks(String username, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findByUsernameOrderByCreatedAtDesc(username, pageable);
    }

    /**
     * 按类型获取用户作品列表（用于创作页面历史记录）
     * @param username 用户名
     * @param workType 作品类型
     * @param includeProcessing 是否包含正在处理中的作品
     * @param page 页码
     * @param size 每页数量
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getUserWorksByType(String username, CommonTaskType workType, boolean includeProcessing, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        if (includeProcessing) {
            return userWorkRepository.findByUsernameAndWorkTypeOrderByCreatedAtDesc(username, workType, pageable);
        } else {
            return userWorkRepository.findByUsernameAndWorkTypeAndStatusOrderByCreatedAtDesc(username, workType, UserWork.WorkStatus.COMPLETED, pageable);
        }
    }

    /**
     * 获取用户正在进行中的作品（包括PROCESSING和PENDING状态）
     */
    @Transactional(readOnly = true)
    public java.util.List<UserWork> getProcessingWorks(String username) {
        return userWorkRepository.findByUsernameAndProcessingOrPendingOrderByCreatedAtDesc(username);
    }

    /**
     * 获取用户作品详情
     */
    @Transactional(readOnly = true)
    public UserWork getUserWorkDetail(Long workId, String username) {
        Optional<UserWork> workOpt = userWorkRepository.findById(workId);
        if (workOpt.isEmpty()) {
            throw new RuntimeException("作品不存在");
        }

        UserWork work = workOpt.get();
        if (!work.getUsername().equals(username)) {
            throw new RuntimeException("无权访问该作品");
        }

        return work;
    }

    /**
     * 更新作品信息
     */
    @Transactional
    public UserWork updateWork(Long workId, String username, String title, String description, String tags, Boolean isPublic) {
        UserWork work = getUserWorkDetail(workId, username);
        
        if (title != null && !title.trim().isEmpty()) {
            work.setTitle(title.trim());
        }
        
        if (description != null) {
            work.setDescription(description);
        }
        
        if (tags != null) {
            work.setTags(tags);
        }
        
        if (isPublic != null) {
            work.setIsPublic(isPublic);
        }
        
        work.setUpdatedAt(LocalDateTime.now());
        work = userWorkRepository.save(work);
        
        logger.info("更新作品信息成功: {}, 用户: {}", workId, username);
        return work;
    }

    /**
     * 删除作品（软删除）
     * 如果是分镜图作品，同时删除对应的分镜视频作品
     */
    @Transactional
    public boolean deleteWork(Long workId, String username) {
        Optional<UserWork> workOpt = userWorkRepository.findById(workId);
        if (workOpt.isEmpty()) {
            return false;
        }

        UserWork work = workOpt.get();
        if (!work.getUsername().equals(username)) {
            throw new RuntimeException("无权删除该作品");
        }

        int result = userWorkRepository.softDeleteWork(workId, username, LocalDateTime.now());
        logger.info("删除作品成功: {}, 用户: {}", workId, username);
        
        // 如果是分镜图作品（task_id 以 _image 结尾），同时删除对应的分镜视频作品
        String taskId = work.getTaskId();
        if (taskId != null && taskId.endsWith("_image")) {
            String videoTaskId = taskId.replace("_image", "");
            Optional<UserWork> videoWorkOpt = userWorkRepository.findByTaskId(videoTaskId);
            if (videoWorkOpt.isPresent()) {
                UserWork videoWork = videoWorkOpt.get();
                userWorkRepository.softDeleteWork(videoWork.getId(), username, LocalDateTime.now());
                logger.info("同时删除分镜视频作品: {}, taskId: {}", videoWork.getId(), videoTaskId);
            }
        }
        
        // 如果是分镜视频作品，同时删除对应的分镜图作品
        if (taskId != null && work.getWorkType() == CommonTaskType.STORYBOARD_VIDEO) {
            String imageTaskId = taskId + "_image";
            Optional<UserWork> imageWorkOpt = userWorkRepository.findByTaskId(imageTaskId);
            if (imageWorkOpt.isPresent()) {
                UserWork imageWork = imageWorkOpt.get();
                userWorkRepository.softDeleteWork(imageWork.getId(), username, LocalDateTime.now());
                logger.info("同时删除分镜图作品: {}, taskId: {}", imageWork.getId(), imageTaskId);
            }
        }
        
        return result > 0;
    }

    /**
     * 批量删除作品（软删除）
     * 自动处理分镜图/分镜视频的关联删除，返回实际删除数量
     */
    @Transactional
    public Map<String, Object> batchDeleteWorks(List<Long> workIds, String username) {
        Map<String, Object> result = new HashMap<>();

        if (workIds == null || workIds.isEmpty()) {
            result.put("deletedCount", 0);
            result.put("totalRequested", 0);
            return result;
        }

        // 查询属于该用户且未删除的作品
        List<UserWork> works = userWorkRepository.findAllByIdInAndUsername(workIds, username);
        if (works.isEmpty()) {
            result.put("deletedCount", 0);
            result.put("totalRequested", workIds.size());
            return result;
        }

        // 收集需要额外删除的关联分镜作品 ID
        Set<Long> allIdsToDelete = new HashSet<>();
        for (UserWork work : works) {
            allIdsToDelete.add(work.getId());

            String taskId = work.getTaskId();
            if (taskId == null) continue;

            // 分镜图 → 关联删除分镜视频
            if (taskId.endsWith("_image")) {
                String videoTaskId = taskId.replace("_image", "");
                userWorkRepository.findByTaskId(videoTaskId).ifPresent(
                    videoWork -> allIdsToDelete.add(videoWork.getId()));
            }
            // 分镜视频 → 关联删除分镜图
            if (work.getWorkType() == CommonTaskType.STORYBOARD_VIDEO) {
                String imageTaskId = taskId + "_image";
                userWorkRepository.findByTaskId(imageTaskId).ifPresent(
                    imageWork -> allIdsToDelete.add(imageWork.getId()));
            }
        }

        LocalDateTime now = LocalDateTime.now();
        int deletedCount = userWorkRepository.batchSoftDeleteWorks(
            new ArrayList<>(allIdsToDelete), username, now);

        logger.info("批量删除作品: 用户={}, 请求数={}, 实际删除数={}（含关联分镜）",
            username, workIds.size(), deletedCount);

        result.put("deletedCount", deletedCount);
        result.put("totalRequested", workIds.size());
        return result;
    }

    /**
     * 根据任务ID更新作品状态
     * 使用 REQUIRES_NEW 传播行为，防止内部异常导致外部事务回滚
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateWorkStatusByTaskId(String taskId, UserWork.WorkStatus status) {
        Optional<UserWork> workOpt = userWorkRepository.findByTaskId(taskId);
        if (workOpt.isPresent()) {
            UserWork work = workOpt.get();
            work.setStatus(status);
            work.setUpdatedAt(LocalDateTime.now());
            userWorkRepository.save(work);
            logger.info("更新作品状态: taskId={}, status={}", taskId, status);
        } else {
            logger.warn("未找到对应的作品记录: taskId={}", taskId);
        }
    }

    /**
     * 任务完成时更新作品状态和结果URL
     * 使用 REQUIRES_NEW 传播行为，防止内部异常导致外部事务回滚
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateWorkOnComplete(String taskId, String resultUrl, UserWork.WorkStatus status) {
        Optional<UserWork> workOpt = userWorkRepository.findByTaskId(taskId);
        if (workOpt.isPresent()) {
            UserWork work = workOpt.get();
            work.setStatus(status);
            work.setResultUrl(resultUrl);
            work.setUpdatedAt(LocalDateTime.now());
            userWorkRepository.save(work);
            logger.info("任务完成，更新作品: taskId={}, status={}, resultUrl={}", 
                taskId, status, resultUrl != null ? resultUrl.substring(0, Math.min(50, resultUrl.length())) + "..." : "null");
        } else {
            logger.warn("未找到对应的作品记录: taskId={}", taskId);
        }
    }

    /**
     * 获取公开作品列表
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getPublicWorks(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findPublicWorksOrderByCreatedAtDesc(pageable);
    }

    /**
     * 根据类型获取公开作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getPublicWorksByType(CommonTaskType workType, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findPublicWorksByTypeOrderByCreatedAtDesc(workType, pageable);
    }

    /**
     * 搜索公开作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> searchPublicWorks(String keyword, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findPublicWorksByPromptOrderByCreatedAtDesc(keyword, pageable);
    }

    /**
     * 根据标签搜索作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> searchPublicWorksByTag(String tag, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findPublicWorksByTagOrderByCreatedAtDesc(tag, pageable);
    }

    /**
     * 获取热门作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getPopularWorks(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findPopularWorksOrderByViewCountDesc(pageable);
    }

    /**
     * 获取最新作品
     */
    @Transactional(readOnly = true)
    public Page<UserWork> getLatestWorks(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userWorkRepository.findLatestWorksOrderByCreatedAtDesc(pageable);
    }

    /**
     * 增加浏览次数
     */
    @Transactional
    public void incrementViewCount(Long workId) {
        userWorkRepository.incrementViewCount(workId, LocalDateTime.now());
    }

    /**
     * 增加点赞次数
     */
    @Transactional
    public void incrementLikeCount(Long workId) {
        userWorkRepository.incrementLikeCount(workId, LocalDateTime.now());
    }

    /**
     * 增加下载次数
     */
    @Transactional
    public void incrementDownloadCount(Long workId) {
        userWorkRepository.incrementDownloadCount(workId, LocalDateTime.now());
    }

    /**
     * 获取用户作品统计
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getUserWorkStats(String username) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Object[] stats = userWorkRepository.getUserWorkStats(username);
            
            // 安全地处理查询结果
            if (stats != null && stats.length >= 4) {
                result.put("completedCount", stats[0] != null ? stats[0] : 0);
                result.put("processingCount", stats[1] != null ? stats[1] : 0);
                result.put("failedCount", stats[2] != null ? stats[2] : 0);
                result.put("totalPointsCost", stats[3] != null ? stats[3] : 0);
            } else {
                // 如果查询结果格式不正确，使用默认值
                result.put("completedCount", 0);
                result.put("processingCount", 0);
                result.put("failedCount", 0);
                result.put("totalPointsCost", 0);
            }
        } catch (Exception e) {
            // 如果查询失败，使用默认值
            logger.warn("获取用户作品统计失败，使用默认值: " + e.getMessage());
            result.put("completedCount", 0);
            result.put("processingCount", 0);
            result.put("failedCount", 0);
            result.put("totalPointsCost", 0);
        }
        
        result.put("totalCount", userWorkRepository.countByUsername(username));
        result.put("publicCount", userWorkRepository.countPublicWorksByUsername(username));
        
        return result;
    }

    /**
     * 清理过期失败作品
     */
    @Transactional
    public int cleanupExpiredFailedWorks() {
        LocalDateTime expiredDate = LocalDateTime.now().minusDays(30);
        return userWorkRepository.deleteExpiredFailedWorks(expiredDate);
    }

    /**
     * 根据任务ID获取作品
     */
    @Transactional(readOnly = true)
    public Optional<UserWork> getWorkByTaskId(String taskId) {
        return userWorkRepository.findByTaskId(taskId);
    }

    /**
     * 直接创建作品记录
     */
    @Transactional
    public UserWork createWork(UserWork work) {
        if (work.getStatus() == null) {
            work.setStatus(UserWork.WorkStatus.PROCESSING);
        }
        if (work.getPointsCost() == null) {
            work.setPointsCost(0);
        }
        if (work.getIsPublic() == null) {
            work.setIsPublic(Boolean.FALSE);
        }
        if (work.getViewCount() == null) {
            work.setViewCount(0);
        }
        if (work.getLikeCount() == null) {
            work.setLikeCount(0);
        }
        if (work.getDownloadCount() == null) {
            work.setDownloadCount(0);
        }
        work.setUpdatedAt(LocalDateTime.now());
        if (work.getCreatedAt() == null) {
            work.setCreatedAt(LocalDateTime.now());
        }
        return userWorkRepository.save(work);
    }

    /**
     * 更新作品状态
     */
    @Transactional
    public void updateWorkStatus(String taskId, UserWork.WorkStatus status) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime completedAt = status == UserWork.WorkStatus.COMPLETED ? now : null;
        
        int result = userWorkRepository.updateStatusByTaskId(taskId, status, now, completedAt);
        if (result > 0) {
            logger.info("更新作品状态成功: {} -> {}", taskId, status);
        }
    }

    /**
     * 更新作品状态和结果URL（级联更新时使用）
     */
    @Transactional
    public void updateWorkStatusWithResult(String taskId, UserWork.WorkStatus status, String resultUrl) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime completedAt = (status == UserWork.WorkStatus.COMPLETED || status == UserWork.WorkStatus.FAILED) ? now : null;
        
        // 先更新状态
        int result = userWorkRepository.updateStatusByTaskId(taskId, status, now, completedAt);
        
        // 如果有结果URL且状态为完成，同时更新URL
        if (resultUrl != null && !resultUrl.isEmpty() && status == UserWork.WorkStatus.COMPLETED) {
            userWorkRepository.updateResultUrlByTaskId(taskId, resultUrl, now);
        }
        
        if (result > 0) {
            logger.info("更新作品状态和结果成功: taskId={}, status={}, hasResultUrl={}", taskId, status, resultUrl != null);
        }
    }

    /**
     * 更新作品结果URL
     */
    @Transactional
    public void updateWorkResultUrl(String taskId, String resultUrl) {
        int result = userWorkRepository.updateResultUrlByTaskId(taskId, resultUrl, LocalDateTime.now());
        if (result > 0) {
            logger.info("更新作品结果URL成功: {} -> {}", taskId, resultUrl);
        }
    }

    /**
     * 获取作品用于下载（包含权限验证）
     */
    @Transactional(readOnly = true)
    public UserWork getWorkForDownload(Long workId, String username) {
        Optional<UserWork> workOpt = userWorkRepository.findById(workId);
        if (workOpt.isEmpty()) {
            throw new RuntimeException("作品不存在");
        }

        UserWork work = workOpt.get();
        
        // 检查作品是否已完成
        if (work.getStatus() != UserWork.WorkStatus.COMPLETED) {
            throw new RuntimeException("作品尚未完成，无法下载");
        }

        // 检查是否有resultUrl
        if (work.getResultUrl() == null || work.getResultUrl().isEmpty()) {
            throw new RuntimeException("作品资源不可用");
        }

        // 权限验证：只允许作品所有者下载
        if (!work.getUsername().equals(username)) {
            throw new RuntimeException("无权下载该作品");
        }

        return work;
    }
}
