package com.dora.service.impl;

import com.alibaba.fastjson.JSON;
import com.dora.dto.PlazaWorkDto.*;
import com.dora.entity.AiTask;
import com.dora.entity.PlazaWork;
import com.dora.entity.PlazaWorkLike;
import com.dora.mapper.AiTaskMapper;
import com.dora.mapper.PlazaWorkLikeMapper;
import com.dora.mapper.PlazaWorkMapper;
import com.dora.service.PlazaService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 广场服务实现
 * 
 * @author 1818AI
 * @since 2025-10-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PlazaServiceImpl implements PlazaService {

    private final PlazaWorkMapper plazaWorkMapper;
    private final PlazaWorkLikeMapper plazaWorkLikeMapper;
    private final AiTaskMapper aiTaskMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkDetailResponse publishWork(Long userId, PublishWorkRequest request) {
        log.info("用户 {} 发布作品，任务编号: {}", userId, request.getTaskNo());
        
        // 1. 验证任务是否存在且属于当前用户
        AiTask task = aiTaskMapper.findByTaskNo(request.getTaskNo());
        if (task == null) {
            throw new IllegalArgumentException("任务不存在: " + request.getTaskNo());
        }
        if (!task.getUserId().equals(userId)) {
            throw new IllegalArgumentException("无权发布该任务的作品");
        }
        if (!"completed".equals(task.getStatus())) {
            throw new IllegalArgumentException("只能发布已完成的任务");
        }
        
        // 2. 检查该任务是否已经发布过
        PlazaWork existingWork = plazaWorkMapper.findByTaskNo(request.getTaskNo());
        if (existingWork != null) {
            throw new IllegalArgumentException("该任务已经发布过，作品编号: " + existingWork.getWorkNo());
        }
        
        // 3. 生成唯一的workNo
        String workNo = generateWorkNo();
        
        // 4. 构建作品实体
        PlazaWork plazaWork = PlazaWork.builder()
                .workNo(workNo)
                .userId(userId)
                .taskNo(task.getTaskNo())
                .taskType(task.getTaskType())
                .modelName(task.getModelName())
                .prompt(task.getPrompt())
                .resultUrl(task.getResultUrl())
                .imageUrl(task.getImageUrl())
                .aspectRatio(task.getAspectRatio())
                .title(request.getTitle())
                .description(request.getDescription())
                .tags(request.getTags() != null ? JSON.toJSONString(request.getTags()) : null)
                .isPublic(request.getIsPublic() ? 1 : 0)
                .status("published")
                .auditStatus("pending")
                .build();
        
        // 5. 插入数据库
        plazaWorkMapper.insert(plazaWork);
        
        log.info("作品发布成功，workNo: {}, taskNo: {}", workNo, request.getTaskNo());
        
        // 6. 返回作品详情
        return getWorkDetail(userId, workNo);
    }

    @Override
    public WorkListResponse getPlazaWorks(Long userId, WorkQueryRequest request) {
        log.info("查询广场作品列表，taskType: {}, sortBy: {}, page: {}, size: {}", 
                 request.getTaskType(), request.getSortBy(), request.getPage(), request.getSize());
        
        int offset = (request.getPage() - 1) * request.getSize();
        
        // 1. 查询作品列表
        List<Map<String, Object>> workMaps = plazaWorkMapper.findPublicWorksList(
                request.getTaskType(),
                request.getSortBy(),
                offset,
                request.getSize()
        );
        
        // 2. 统计总数
        long total = plazaWorkMapper.countPublicWorks(request.getTaskType());
        
        // 3. 提取作品ID列表
        List<Long> workIds = workMaps.stream()
                .map(map -> (Long) map.get("id"))
                .collect(Collectors.toList());
        
        // 4. 批量查询当前用户的点赞状态
        Set<Long> likedWorkIds = new HashSet<>();
        if (userId != null && !workIds.isEmpty()) {
            likedWorkIds = new HashSet<>(plazaWorkLikeMapper.findLikedWorkIds(userId, workIds));
        }
        
        // 5. 转换为DTO
        List<WorkListItemResponse> list = new ArrayList<>();
        for (Map<String, Object> workMap : workMaps) {
            Long workId = (Long) workMap.get("id");
            list.add(convertToListItem(workMap, likedWorkIds.contains(workId)));
        }
        
        return WorkListResponse.builder()
                .total(total)
                .list(list)
                .build();
    }

    @Override
    public WorkDetailResponse getWorkDetail(Long userId, String workNo) {
        log.info("查询作品详情，workNo: {}", workNo);
        
        // 1. 查询作品（包含作者信息）
        // 注意：统一转换为大写，因为数据库中的work_no都是大写格式（WORK-xxx）
        String normalizedWorkNo = workNo.toUpperCase();
        Map<String, Object> workMap = plazaWorkMapper.findWorkDetailByWorkNo(normalizedWorkNo);
        if (workMap == null) {
            throw new IllegalArgumentException("作品不存在: " + workNo);
        }
        
        // 2. 检查是否点赞
        boolean isLiked = false;
        if (userId != null) {
            Long workId = (Long) workMap.get("id");
            isLiked = plazaWorkLikeMapper.existsByWorkIdAndUserId(workId, userId) > 0;
        }
        
        // 3. 转换为DTO
        return convertToDetailResponse(workMap, isLiked);
    }

    @Override
    public WorkDetailResponse getWorkDetailByTaskNo(Long userId, String taskNo) {
        log.info("通过任务编号查询作品详情（不记录浏览），taskNo: {}", taskNo);
        
        // 1. 统一转换为大写，因为数据库中的task_no都是大写格式（TASK-xxx）
        String normalizedTaskNo = taskNo.toUpperCase();
        
        // 2. 先查询广场作品（已发布）
        Map<String, Object> workMap = plazaWorkMapper.findWorkDetailByTaskNo(normalizedTaskNo);
        
        if (workMap != null) {
            // 2.1 找到广场作品，检查是否点赞
            boolean isLiked = false;
            if (userId != null) {
                Long workId = (Long) workMap.get("id");
                isLiked = plazaWorkLikeMapper.existsByWorkIdAndUserId(workId, userId) > 0;
            }
            return convertToDetailResponse(workMap, isLiked);
        }
        
        // 3. 广场中没找到，查询AI任务表（未发布的任务）
        log.info("广场中未找到作品，尝试从任务表查询 - taskNo: {}", normalizedTaskNo);
        Map<String, Object> taskMap = aiTaskMapper.findTaskDetailByTaskNo(normalizedTaskNo);
        
        if (taskMap == null) {
            throw new IllegalArgumentException("该任务不存在: " + taskNo);
        }
        
        // 4. 从任务数据构建作品详情响应（未发布状态）
        return convertTaskToWorkDetail(taskMap);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LikeResponse likeWork(Long userId, String workNo) {
        log.info("用户 {} 点赞作品 {}", userId, workNo);
        
        // 统一转换为大写
        String normalizedWorkNo = workNo.toUpperCase();
        
        // 1. 查询作品
        PlazaWork work = plazaWorkMapper.findByWorkNo(normalizedWorkNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在: " + workNo);
        }
        
        // 2. 检查是否已经点赞
        if (plazaWorkLikeMapper.existsByWorkIdAndUserId(work.getId(), userId) > 0) {
            throw new IllegalArgumentException("已经点赞过该作品");
        }
        
        // 3. 插入点赞记录
        PlazaWorkLike like = PlazaWorkLike.builder()
                .workId(work.getId())
                .userId(userId)
                .build();
        plazaWorkLikeMapper.insert(like);
        
        // 4. 更新作品点赞数
        plazaWorkMapper.incrementLikeCount(work.getId());
        
        // 5. 获取最新点赞数
        PlazaWork updatedWork = plazaWorkMapper.findByWorkNo(normalizedWorkNo);
        
        return LikeResponse.builder()
                .isLiked(true)
                .likeCount(updatedWork.getLikeCount())
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LikeResponse unlikeWork(Long userId, String workNo) {
        log.info("用户 {} 取消点赞作品 {}", userId, workNo);
        
        // 统一转换为大写
        String normalizedWorkNo = workNo.toUpperCase();
        
        // 1. 查询作品
        PlazaWork work = plazaWorkMapper.findByWorkNo(normalizedWorkNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在: " + workNo);
        }
        
        // 2. 删除点赞记录
        int deleted = plazaWorkLikeMapper.deleteByWorkIdAndUserId(work.getId(), userId);
        if (deleted == 0) {
            throw new IllegalArgumentException("未点赞过该作品");
        }
        
        // 3. 更新作品点赞数
        plazaWorkMapper.decrementLikeCount(work.getId());
        
        // 4. 获取最新点赞数
        PlazaWork updatedWork = plazaWorkMapper.findByWorkNo(normalizedWorkNo);
        
        return LikeResponse.builder()
                .isLiked(false)
                .likeCount(updatedWork.getLikeCount())
                .build();
    }

    @Override
    public WorkListResponse getUserWorks(Long userId, WorkQueryRequest request) {
        log.info("查询用户 {} 的作品列表", userId);
        
        int offset = (request.getPage() - 1) * request.getSize();
        
        // 1. 查询用户作品列表
        List<PlazaWork> works = plazaWorkMapper.findUserWorks(
                userId,
                request.getStatus(),
                offset,
                request.getSize()
        );
        
        // 2. 统计总数
        long total = plazaWorkMapper.countUserWorks(userId, request.getStatus());
        
        // 3. 转换为DTO
        List<WorkListItemResponse> list = works.stream()
                .map(work -> convertToListItemFromEntity(work, true)) // 自己的作品默认已点赞状态为true
                .collect(Collectors.toList());
        
        return WorkListResponse.builder()
                .total(total)
                .list(list)
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWork(Long userId, String workNo) {
        log.info("用户 {} 删除作品 {}", userId, workNo);
        
        // 统一转换为大写
        String normalizedWorkNo = workNo.toUpperCase();
        
        int deleted = plazaWorkMapper.deleteByWorkNoAndUserId(normalizedWorkNo, userId);
        if (deleted == 0) {
            throw new IllegalArgumentException("作品不存在或无权删除");
        }
        
        log.info("作品删除成功，workNo: {}", workNo);
    }

    @Override
    public PlazaStatsResponse getPlazaStats() {
        log.info("查询广场统计数据");
        
        // 1. 获取总体统计
        Map<String, Object> stats = plazaWorkMapper.getPlazaStats();
        
        // 2. 按类型统计
        List<Map<String, Object>> typeStats = plazaWorkMapper.countWorksByType();
        Map<String, Long> worksByType = typeStats.stream()
                .collect(Collectors.toMap(
                        map -> (String) map.get("task_type"),
                        map -> ((Number) map.get("count")).longValue()
                ));
        
        return PlazaStatsResponse.builder()
                .totalWorks(((Number) stats.getOrDefault("total_works", 0)).longValue())
                .totalViews(((Number) stats.getOrDefault("total_views", 0)).longValue())
                .totalLikes(((Number) stats.getOrDefault("total_likes", 0)).longValue())
                .worksByType(worksByType)
                .build();
    }

    @Override
    public void recordView(String workNo, Long userId) {
        log.debug("记录作品浏览，workNo: {}, userId: {}", workNo, userId);
        
        // 统一转换为大写
        String normalizedWorkNo = workNo.toUpperCase();
        PlazaWork work = plazaWorkMapper.findByWorkNo(normalizedWorkNo);
        if (work != null) {
            plazaWorkMapper.incrementViewCount(work.getId());
        }
    }

    @Override
    public UserLikedWorksResponse getUserLikedWorks(Long userId, Integer page, Integer size) {
        log.info("查询用户 {} 的点赞作品列表，page: {}, size: {}", userId, page, size);
        
        int offset = (page - 1) * size;
        
        // 1. 查询用户点赞的作品列表（包含作品信息和作者信息）
        List<Map<String, Object>> likedWorkMaps = plazaWorkMapper.findUserLikedWorks(userId, offset, size);
        
        // 2. 统计总数
        long total = plazaWorkLikeMapper.countUserLikes(userId);
        
        // 3. 转换为DTO
        List<LikedWorkItem> list = new ArrayList<>();
        for (Map<String, Object> workMap : likedWorkMaps) {
            list.add(convertToLikedWorkItem(workMap));
        }
        
        log.info("查询用户点赞作品列表成功，userId: {}, 返回 {} 条，总数: {}", userId, list.size(), total);
        
        return UserLikedWorksResponse.builder()
                .total(total)
                .list(list)
                .build();
    }

    /**
     * 生成作品编号
     */
    private String generateWorkNo() {
        return "WORK-" + System.currentTimeMillis() + "-" + (int)(Math.random() * 10000);
    }

    /**
     * 转换Map为WorkListItemResponse
     */
    private WorkListItemResponse convertToListItem(Map<String, Object> workMap, boolean isLiked) {
        String tagsJson = (String) workMap.get("tags");
        List<String> tags = tagsJson != null ? JSON.parseArray(tagsJson, String.class) : Collections.emptyList();
        
        WorkAuthorDto author = WorkAuthorDto.builder()
                .userId((Long) workMap.get("user_id"))
                .nickname((String) workMap.get("nickname"))
                .avatarUrl((String) workMap.get("avatar_url"))
                .build();
        
        return WorkListItemResponse.builder()
                .workNo((String) workMap.get("work_no"))
                .taskType((String) workMap.get("task_type"))
                .modelName((String) workMap.get("model_name"))
                .prompt((String) workMap.get("prompt"))
                .resultUrl((String) workMap.get("result_url"))
                .title((String) workMap.get("title"))
                .tags(tags)
                .viewCount((Integer) workMap.get("view_count"))
                .likeCount((Integer) workMap.get("like_count"))
                .isLiked(isLiked)
                .author(author)
                .createTime((LocalDateTime) workMap.get("create_time"))
                .build();
    }

    /**
     * 转换Map为WorkDetailResponse
     */
    private WorkDetailResponse convertToDetailResponse(Map<String, Object> workMap, boolean isLiked) {
        String tagsJson = (String) workMap.get("tags");
        List<String> tags = tagsJson != null ? JSON.parseArray(tagsJson, String.class) : Collections.emptyList();
        
        WorkAuthorDto author = WorkAuthorDto.builder()
                .userId((Long) workMap.get("user_id"))
                .nickname((String) workMap.get("nickname"))
                .avatarUrl((String) workMap.get("avatar_url"))
                .build();
        
        return WorkDetailResponse.builder()
                .workNo((String) workMap.get("work_no"))
                .taskNo((String) workMap.get("task_no"))
                .taskType((String) workMap.get("task_type"))
                .modelName((String) workMap.get("model_name"))
                .prompt((String) workMap.get("prompt"))
                .resultUrl((String) workMap.get("result_url"))
                .imageUrl((String) workMap.get("image_url"))
                .aspectRatio((String) workMap.get("aspect_ratio"))
                .title((String) workMap.get("title"))
                .description((String) workMap.get("description"))
                .tags(tags)
                .viewCount((Integer) workMap.get("view_count"))
                .likeCount((Integer) workMap.get("like_count"))
                .shareCount((Integer) workMap.get("share_count"))
                .isLiked(isLiked)
                .author(author)
                .createTime((LocalDateTime) workMap.get("create_time"))
                .updateTime((LocalDateTime) workMap.get("update_time"))
                .build();
    }

    /**
     * 转换实体为WorkListItemResponse
     */
    private WorkListItemResponse convertToListItemFromEntity(PlazaWork work, boolean isLiked) {
        List<String> tags = work.getTags() != null ? JSON.parseArray(work.getTags(), String.class) : Collections.emptyList();
        
        // 注意：这里author信息需要单独查询用户表，或者使用上面的联表查询
        WorkAuthorDto author = WorkAuthorDto.builder()
                .userId(work.getUserId())
                .nickname("") // 需要查询用户表
                .avatarUrl("")
                .build();
        
        return WorkListItemResponse.builder()
                .workNo(work.getWorkNo())
                .taskType(work.getTaskType())
                .modelName(work.getModelName())
                .prompt(work.getPrompt())
                .resultUrl(work.getResultUrl())
                .title(work.getTitle())
                .tags(tags)
                .viewCount(work.getViewCount())
                .likeCount(work.getLikeCount())
                .isLiked(isLiked)
                .author(author)
                .createTime(work.getCreateTime())
                .build();
    }

    /**
     * 转换Map为LikedWorkItem
     */
    private LikedWorkItem convertToLikedWorkItem(Map<String, Object> workMap) {
        String tagsJson = (String) workMap.get("tags");
        List<String> tags = tagsJson != null ? JSON.parseArray(tagsJson, String.class) : Collections.emptyList();
        
        WorkAuthorDto author = WorkAuthorDto.builder()
                .userId((Long) workMap.get("user_id"))
                .nickname((String) workMap.get("nickname"))
                .avatarUrl((String) workMap.get("avatar_url"))
                .build();
        
        return LikedWorkItem.builder()
                .likeId((Long) workMap.get("like_id"))
                .workNo((String) workMap.get("work_no"))
                .taskType((String) workMap.get("task_type"))
                .modelName((String) workMap.get("model_name"))
                .prompt((String) workMap.get("prompt"))
                .resultUrl((String) workMap.get("result_url"))
                .title((String) workMap.get("title"))
                .tags(tags)
                .viewCount((Integer) workMap.get("view_count"))
                .likeCount((Integer) workMap.get("like_count"))
                .author(author)
                .likedTime((LocalDateTime) workMap.get("liked_time"))
                .createTime((LocalDateTime) workMap.get("create_time"))
                .build();
    }

    /**
     * 将任务数据转换为作品详情响应（用于未发布的任务）
     * 注意：MyBatis返回的HashMap中，字段名保持数据库的下划线格式
     */
    private WorkDetailResponse convertTaskToWorkDetail(Map<String, Object> taskMap) {
        // 构建作者信息（下划线格式的字段名）
        WorkAuthorDto author = WorkAuthorDto.builder()
                .userId((Long) taskMap.get("user_id"))
                .nickname((String) taskMap.get("nickname"))
                .avatarUrl((String) taskMap.get("avatar_url"))
                .build();
        
        // 未发布的任务，使用任务编号作为标识，社交数据设为0
        // 注意：从Map中获取值时使用下划线格式的key（与数据库字段名一致）
        return WorkDetailResponse.builder()
                .workNo(null)  // 未发布，无作品编号
                .taskNo((String) taskMap.get("task_no"))
                .taskType((String) taskMap.get("task_type"))
                .modelName((String) taskMap.get("model_name"))
                .prompt((String) taskMap.get("prompt"))
                .resultUrl((String) taskMap.get("result_url"))  // 任务完成后才有值
                .imageUrl((String) taskMap.get("image_url"))    // 参考图URL（图生视频才有）
                .aspectRatio((String) taskMap.get("aspect_ratio"))
                .title(null)  // 未发布，无标题
                .description(null)  // 未发布，无描述
                .tags(Collections.emptyList())  // 未发布，无标签
                .viewCount(0)  // 未发布，浏览数为0
                .likeCount(0)  // 未发布，点赞数为0
                .shareCount(0)  // 未发布，分享数为0
                .isLiked(false)  // 未发布，不可点赞
                .author(author)
                .createTime((LocalDateTime) taskMap.get("create_time"))
                .updateTime((LocalDateTime) taskMap.get("update_time"))
                // 任务状态信息（帮助前端判断任务完成情况）
                .taskStatus((String) taskMap.get("status"))
                .taskProgress((Integer) taskMap.get("progress"))
                .errorMessage((String) taskMap.get("error_message"))
                .build();
    }
}

