package com.dora.service.impl;

import com.dora.dto.VodDto;
import com.dora.entity.ContentRevenueStage;
import com.dora.entity.Video;
import com.dora.mapper.VideoMapper;
import com.dora.mapper.VideoViewStatMapper;
import com.dora.service.ContentRevenueStageService;
import com.dora.service.VideoViewStatService;
import com.dora.util.MembershipUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 视频观看统计服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VideoViewStatServiceImpl implements VideoViewStatService {

    private final VideoMapper videoMapper;
    private final VideoViewStatMapper videoViewStatMapper;
    private final ContentRevenueStageService contentRevenueStageService;
    private final MembershipUtil membershipUtil;

    @Override
    @Transactional
    public VodDto.ViewCountUpdateInfo recordVideoView(String videoId, Long userId, Long courseId, Long chapterId) {
        try {
            log.info("记录视频观看 - videoId: {}, userId: {}, courseId: {}, chapterId: {}", 
                    videoId, userId, courseId, chapterId);

            // 1. 根据阿里云视频ID查找本地视频记录
            Video video = videoMapper.selectByVodVideoId(videoId);
            if (video == null) {
                log.warn("未找到对应的本地视频记录 - vodVideoId: {}，可能是工作流视频或其他类型视频", videoId);
                throw new RuntimeException("未找到对应的本地视频记录，视频ID: " + videoId);
            }

            // 2. 获取更新前的播放次数
            Integer previousViewCount = video.getViewCount() != null ? video.getViewCount() : 0;
            
            // 3. 检查用户是否已观看过该视频
            Integer viewedCount = videoViewStatMapper.checkUserViewedVideo(video.getId(), userId);
            boolean isFirstView = viewedCount == null || viewedCount == 0;
            
            Integer viewStatId = 1; // 临时默认值
            Integer currentViewCount = previousViewCount;
            
            if (isFirstView) {
                // 首次观看：插入新记录并增加播放次数
                log.info("用户首次观看视频 - videoId: {}, userId: {}", video.getId(), userId);
                
                // 插入观看记录
                Map<String, Object> params = new HashMap<>();
                params.put("videoId", video.getId());
                params.put("ownerId", video.getOwnerId());
                params.put("viewUserId", userId);
                params.put("viewDuration", 0); // 初始观看时长为0
                videoViewStatMapper.insertViewRecord(params);
                
                // 更新视频播放次数
                Integer updatedRows = videoViewStatMapper.updateVideoViewCount(video.getId());
                if (updatedRows == 0) {
                    log.warn("更新视频播放次数失败 - videoId: {}", video.getId());
                    throw new RuntimeException("更新播放次数失败");
                }
                
                currentViewCount = previousViewCount + 1;
                log.info("首次观看，播放次数增加 - videoId: {}, 播放次数: {} -> {}", 
                        video.getId(), previousViewCount, currentViewCount);
                
                // 检查收益阶段 (工作流视频不参与收益分成，其他视频包括免费课程视频都参与分成)
                if (!contentRevenueStageService.isWorkflowVideo(videoId)) {
                    // 检查用户是否为纯兑换会员，兑换会员不参与收益计算
                    if (membershipUtil.isExchangeMemberWithoutRevenue(userId)) {
                        String membershipType = membershipUtil.getMembershipTypeDescription(userId);
                        log.info("{}不参与视频收益计算 - videoId: {}, userId: {}, membershipType: {}", 
                                membershipType, videoId, userId, membershipType);
                    } else {
                        List<ContentRevenueStage> newlyAchievedStages = contentRevenueStageService
                                .checkAndUpdateVideoRevenueStages(video.getId(), video.getOwnerId(), currentViewCount);
                        
                        if (!newlyAchievedStages.isEmpty()) {
                            BigDecimal totalNewRevenue = newlyAchievedStages.stream()
                                    .map(ContentRevenueStage::getRewardAmount)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            
                            log.info("视频观看达到新收益阶段 - videoId: {}, 新达到阶段数: {}, 新获得收益: {} 元", 
                                    video.getId(), newlyAchievedStages.size(), totalNewRevenue);
                        }
                    }
                } else {
                    log.debug("工作流视频不参与收益分成 - videoId: {}", videoId);
                }
                
            } else {
                // 重复观看：仅更新观看时间，不增加播放次数
                log.info("用户重复观看视频 - videoId: {}, userId: {}，仅更新观看时间", video.getId(), userId);
                
                Integer updatedRows = videoViewStatMapper.updateViewTime(video.getId(), userId);
                if (updatedRows == 0) {
                    log.warn("更新观看时间失败 - videoId: {}, userId: {}", video.getId(), userId);
                }
                
                // 播放次数保持不变
                currentViewCount = previousViewCount;
                log.info("重复观看，播放次数不变 - videoId: {}, 播放次数: {}", 
                        video.getId(), currentViewCount);
            }

            // 4. 构建响应信息
            VodDto.ViewCountUpdateInfo viewCountInfo = new VodDto.ViewCountUpdateInfo();
            viewCountInfo.setVideoId(video.getId());
            viewCountInfo.setPreviousViewCount(previousViewCount);
            viewCountInfo.setCurrentViewCount(currentViewCount);
            viewCountInfo.setViewStatId(Long.valueOf(viewStatId));
            viewCountInfo.setUpdateTime(LocalDateTime.now());

            log.info("视频观看记录成功 - videoId: {}, 是否首次观看: {}, 播放次数: {} -> {}", 
                    video.getId(), isFirstView, previousViewCount, currentViewCount);

            return viewCountInfo;

        } catch (Exception e) {
            log.error("记录视频观看失败 - videoId: {}, userId: {}", videoId, userId, e);
            throw new RuntimeException("记录视频观看失败: " + e.getMessage());
        }
    }

    @Override
    public Integer getVideoViewCount(String videoId) {
        try {
            Video video = videoMapper.selectByVodVideoId(videoId);
            return video != null ? video.getViewCount() : 0;
        } catch (Exception e) {
            log.error("获取视频播放次数失败 - videoId: {}", videoId, e);
            return 0;
        }
    }
} 