package com.ycwl.basic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.enums.VideoReviewSourceEnum;
import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.exception.BizException;
import com.ycwl.basic.mapper.OrderMapper;
import com.ycwl.basic.mapper.TaskMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.mapper.VideoReviewMapper;
import com.ycwl.basic.model.pc.order.entity.OrderEntity;
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
import com.ycwl.basic.model.pc.videoreview.dto.AdminVideoReviewLogReqDTO;
import com.ycwl.basic.model.pc.videoreview.dto.AdminVideoReviewLogRespDTO;
import com.ycwl.basic.model.pc.videoreview.dto.VideoPurchaseCheckReqDTO;
import com.ycwl.basic.model.pc.videoreview.dto.VideoPurchaseCheckRespDTO;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.model.pc.videoreview.dto.VideoReviewAddReqDTO;
import com.ycwl.basic.model.pc.videoreview.dto.VideoReviewListReqDTO;
import com.ycwl.basic.model.pc.videoreview.dto.VideoReviewRespDTO;
import com.ycwl.basic.model.pc.videoreview.dto.VideoReviewStatisticsRespDTO;
import com.ycwl.basic.model.pc.videoreview.entity.VideoReviewEntity;
import com.ycwl.basic.service.VideoReviewService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 视频评价Service实现类
 */
@Slf4j
@Service
public class VideoReviewServiceImpl implements VideoReviewService {

    @Autowired
    private VideoReviewMapper videoReviewMapper;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private TaskMapper taskMapper;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addReview(VideoReviewAddReqDTO reqDTO) {
        // 1. 参数校验
        if (reqDTO.getVideoId() == null) {
            throw new BaseException("视频ID不能为空");
        }
        if (reqDTO.getRating() == null || reqDTO.getRating() < 1 || reqDTO.getRating() > 5) {
            throw new BaseException("评分必须在1-5之间");
        }
        if (reqDTO.getSource() == null || reqDTO.getSource().isEmpty()) {
            throw new BaseException("来源不能为空");
        }
        if (!VideoReviewSourceEnum.isValid(reqDTO.getSource())) {
            throw new BaseException("来源值无效,仅支持: ORDER(订单), RENDER(渲染)");
        }

        // 2. 查询视频信息,获取景区ID
        VideoEntity video = videoMapper.getEntity(reqDTO.getVideoId());
        if (video == null) {
            throw new BaseException("视频不存在");
        }

        // 3. 获取当前登录用户(管理员)
        String userIdStr = BaseContextHandler.getUserId();
        if (userIdStr == null || userIdStr.isEmpty()) {
            throw new BaseException("未登录或登录已过期");
        }
        Long creator = Long.valueOf(userIdStr);

        // 4. 构建评价实体
        VideoReviewEntity entity = new VideoReviewEntity();
        entity.setVideoId(reqDTO.getVideoId());
        entity.setScenicId(video.getScenicId());
        entity.setCreator(creator);
        entity.setRating(reqDTO.getRating());
        entity.setContent(reqDTO.getContent());
        entity.setProblemDeviceIds(reqDTO.getProblemDeviceIds());
        entity.setProblemTags(reqDTO.getProblemTags());
        entity.setSource(reqDTO.getSource());
        entity.setSourceId(reqDTO.getSourceId());

        // 5. 插入数据库
        videoReviewMapper.insert(entity);

        log.info("管理员[{}]对视频[{}]添加评价成功,评价ID: {}, 来源: {}, 来源ID: {}",
                creator, reqDTO.getVideoId(), entity.getId(), reqDTO.getSource(), reqDTO.getSourceId());
        return entity.getId();
    }

    @Override
    public PageInfo<VideoReviewRespDTO> getReviewList(VideoReviewListReqDTO reqDTO) {
        // 设置分页参数
        PageHelper.startPage(reqDTO.getPageNum(), reqDTO.getPageSize());

        // 查询列表
        List<VideoReviewRespDTO> list = videoReviewMapper.selectReviewList(reqDTO);

        // 封装分页结果
        return new PageInfo<>(list);
    }

    @Override
    public PageInfo<AdminVideoReviewLogRespDTO> getAdminReviewLogList(AdminVideoReviewLogReqDTO reqDTO) {
        // 设置分页参数
        PageHelper.startPage(reqDTO.getPageNum(), reqDTO.getPageSize());

        // 查询列表
        List<AdminVideoReviewLogRespDTO> list = videoReviewMapper.selectAdminReviewLogList(reqDTO);

        // 封装分页结果
        return new PageInfo<>(list);
    }

    @Override
    public VideoReviewStatisticsRespDTO getStatistics() {
        VideoReviewStatisticsRespDTO statistics = new VideoReviewStatisticsRespDTO();

        // 1. 总评价数
        Long totalCount = videoReviewMapper.countTotal();
        statistics.setTotalCount(totalCount);

        // 2. 平均评分
        Double avgRating = videoReviewMapper.calculateAverageRating();
        if (avgRating != null) {
            statistics.setAverageRating(BigDecimal.valueOf(avgRating).setScale(2, RoundingMode.HALF_UP));
        } else {
            statistics.setAverageRating(BigDecimal.ZERO);
        }

        // 3. 评分分布
        List<Map<String, Object>> ratingDistList = videoReviewMapper.countRatingDistribution();
        Map<Integer, Long> ratingDistribution = new HashMap<>();
        for (Map<String, Object> item : ratingDistList) {
            Integer rating = (Integer) item.get("ratingValue");
            Long count = (Long) item.get("count");
            ratingDistribution.put(rating, count);
        }
        statistics.setRatingDistribution(ratingDistribution);

        // 4. 最近7天趋势
        List<Map<String, Object>> trendList = videoReviewMapper.countRecentTrend(7);
        Map<String, Long> recentTrend = new LinkedHashMap<>();
        for (Map<String, Object> item : trendList) {
            String date = (String) item.get("dateStr");
            Long count = (Long) item.get("count");
            recentTrend.put(date, count);
        }
        statistics.setRecentTrend(recentTrend);

        // 5. 景区排行(前10)
        List<VideoReviewStatisticsRespDTO.ScenicReviewRank> scenicRankList = videoReviewMapper.countScenicRank(10);
        statistics.setScenicRankList(scenicRankList);

        // 6. 问题机位统计
        Map<Long, Long> problemDeviceStatistics = calculateProblemDeviceStatistics();
        statistics.setProblemDeviceStatistics(problemDeviceStatistics);

        return statistics;
    }

    @Override
    public void exportReviews(VideoReviewListReqDTO reqDTO, OutputStream outputStream) throws IOException {
        // 1. 查询所有数据(不分页)
        reqDTO.setPageNum(1);
        reqDTO.setPageSize(Integer.MAX_VALUE);
        List<VideoReviewRespDTO> list = videoReviewMapper.selectReviewList(reqDTO);

        // 2. 创建Excel工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("视频评价数据");

        // 3. 创建标题行样式
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        // 4. 生成表头
        Row headerRow = sheet.createRow(0);
        List<String> headerList = new ArrayList<>();
        headerList.add("评价ID");
        headerList.add("视频ID");
        headerList.add("视频模板名称");
        headerList.add("景区名称");
        headerList.add("评价人名称");
        headerList.add("评分");
        headerList.add("文字评价");
        headerList.add("问题机位ID列表");
        headerList.add("问题标签");
        headerList.add("创建时间");
        headerList.add("更新时间");

        // 设置表头
        for (int i = 0; i < headerList.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headerList.get(i));
            cell.setCellStyle(headerStyle);
        }

        // 5. 填充数据
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int rowNum = 1;

        for (VideoReviewRespDTO review : list) {
            Row row = sheet.createRow(rowNum++);
            int colIndex = 0;

            // 基础信息列
            row.createCell(colIndex++).setCellValue(review.getId());
            row.createCell(colIndex++).setCellValue(review.getVideoId());
            row.createCell(colIndex++).setCellValue(review.getTemplateName() != null ? review.getTemplateName() : "");
            row.createCell(colIndex++).setCellValue(review.getScenicName());
            row.createCell(colIndex++).setCellValue(review.getCreatorName());
            row.createCell(colIndex++).setCellValue(review.getRating());
            row.createCell(colIndex++).setCellValue(review.getContent() != null ? review.getContent() : "");

            // 问题机位ID列表
            List<Long> problemDeviceIds = review.getProblemDeviceIds();
            String problemDeviceIdsStr = (problemDeviceIds != null && !problemDeviceIds.isEmpty())
                    ? problemDeviceIds.toString()
                    : "";
            row.createCell(colIndex++).setCellValue(problemDeviceIdsStr);

            // 问题标签
            List<String> problemTags = review.getProblemTags();
            String problemTagsStr = (problemTags != null && !problemTags.isEmpty())
                    ? String.join(", ", problemTags)
                    : "";
            row.createCell(colIndex++).setCellValue(problemTagsStr);

            // 时间列
            row.createCell(colIndex++).setCellValue(review.getCreateTime() != null ? sdf.format(review.getCreateTime()) : "");
            row.createCell(colIndex).setCellValue(review.getUpdateTime() != null ? sdf.format(review.getUpdateTime()) : "");
        }

        // 6. 自动调整列宽
        for (int i = 0; i < headerList.size(); i++) {
            sheet.autoSizeColumn(i);
        }

        // 7. 写入输出流
        workbook.write(outputStream);
        workbook.close();

        log.info("导出视频评价数据成功,共{}条", list.size());
    }

    @Override
    public VideoPurchaseCheckRespDTO checkVideoPurchase(VideoPurchaseCheckReqDTO reqDTO) {
        // 参数校验
        if (reqDTO.getVideoId() == null) {
            throw new BaseException("视频ID不能为空");
        }

        Long videoId = reqDTO.getVideoId();

        // 查询视频信息
        VideoEntity video = videoMapper.getEntity(videoId);
        if (video == null) {
            throw new BaseException("视频不存在");
        }

        VideoPurchaseCheckRespDTO respDTO = new VideoPurchaseCheckRespDTO();
        respDTO.setVideoId(videoId);

        List<Long> allOrderIds = new ArrayList<>();

        // 情况1：直接购买视频的订单（goods_type=0, goods_id=视频id）
        List<Long> directOrderIds = orderMapper.getOrderIdsByVideoId(videoId);
        if (directOrderIds != null && !directOrderIds.isEmpty()) {
            allOrderIds.addAll(directOrderIds);
            log.info("视频[{}]直接购买订单数: {}", videoId, directOrderIds.size());
        }

        // 情况2：通过购买模板间接拥有（goods_type=-1, goods_id=templateId）
        // 通过video的faceId查询购买模板的订单
        if (video.getFaceId() != null && video.getTemplateId() != null) {
            List<Long> templateOrderIds = orderMapper.getOrderIdsByFaceIdAndTemplateId(
                video.getFaceId(),
                video.getTemplateId()
            );

            if (templateOrderIds != null && !templateOrderIds.isEmpty()) {
                allOrderIds.addAll(templateOrderIds);
                log.info("视频[{}]通过模板[{}]购买订单数: {}, faceId: {}",
                    videoId, video.getTemplateId(), templateOrderIds.size(), video.getFaceId());
            }
        }

        respDTO.setOrderIds(allOrderIds);
        respDTO.setIsPurchased(!allOrderIds.isEmpty());

        log.info("视频[{}]购买检查完成,是否被购买: {}, 总订单数: {}",
            videoId, respDTO.getIsPurchased(), allOrderIds.size());

        return respDTO;
    }

    /**
     * 统计问题机位
     * 统计每个机位被标记为问题的次数
     */
    private Map<Long, Long> calculateProblemDeviceStatistics() {
        List<List<Long>> allProblemDeviceIds = videoReviewMapper.selectAllProblemDeviceIds();

        if (allProblemDeviceIds == null || allProblemDeviceIds.isEmpty()) {
            return new HashMap<>();
        }

        // 统计各机位被标记为问题的次数
        Map<Long, Long> deviceProblemCount = new HashMap<>();
        for (List<Long> problemDeviceIds : allProblemDeviceIds) {
            if (problemDeviceIds == null || problemDeviceIds.isEmpty()) continue;
            for (Long deviceId : problemDeviceIds) {
                deviceProblemCount.put(deviceId, deviceProblemCount.getOrDefault(deviceId, 0L) + 1);
            }
        }

        return deviceProblemCount;
    }
}
