package com.dora.service.impl;

import com.dora.dto.PlazaWorkReportDto;
import com.dora.entity.PlazaWork;
import com.dora.entity.PlazaWorkReport;
import com.dora.entity.PlazaWorkReportLimit;
import com.dora.mapper.PlazaWorkMapper;
import com.dora.mapper.PlazaWorkReportLimitMapper;
import com.dora.mapper.PlazaWorkReportMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.PlazaWorkReportService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 广场作品投诉服务实现
 * 
 * @author 1818AI
 * @since 2025-11-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PlazaWorkReportServiceImpl implements PlazaWorkReportService {

    private final PlazaWorkReportMapper reportMapper;
    private final PlazaWorkReportLimitMapper limitMapper;
    private final PlazaWorkMapper plazaWorkMapper;
    private final UserMapper userMapper;
    
    // 每日投诉限制次数
    private static final int MAX_REPORT_COUNT_PER_DAY = 10;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PlazaWorkReportDto.ReportResponse submitReport(Long userId, PlazaWorkReportDto.SubmitReportRequest request) {
        log.info("用户 {} 提交投诉，作品编号: {}, 投诉类型: {}", userId, request.getWorkNo(), request.getReportType());
        
        // 1. 验证作品是否存在
        PlazaWork work = plazaWorkMapper.findByWorkNo(request.getWorkNo());
        if (work == null) {
            throw new IllegalArgumentException("作品不存在: " + request.getWorkNo());
        }
        
        // 2. 检查是否是自己发布的作品（不能投诉自己的作品）
        if (work.getUserId().equals(userId)) {
            throw new IllegalArgumentException("不能投诉自己发布的作品");
        }
        
        // 3. 检查是否已经投诉过该作品
        PlazaWorkReport existingReport = reportMapper.findByWorkIdAndReporterId(work.getId(), userId);
        if (existingReport != null) {
            throw new IllegalArgumentException("您已经投诉过该作品");
        }
        
        // 4. 检查投诉限制（防止恶意投诉）
        checkReportLimit(userId);
        
        // 5. 生成投诉编号
        String reportNo = generateReportNo();
        
        // 6. 创建投诉记录
        PlazaWorkReport report = PlazaWorkReport.builder()
                .reportNo(reportNo)
                .workId(work.getId())
                .workNo(work.getWorkNo())
                .reporterId(userId)
                .reportType(request.getReportType())
                .reportReason(request.getReportReason())
                .reportStatus("pending")
                .isDeleted(0)
                .build();
        
        reportMapper.insert(report);
        
        // 7. 更新投诉限制计数
        updateReportLimit(userId);
        
        log.info("投诉提交成功，投诉编号: {}", reportNo);
        
        return convertToReportResponse(report);
    }

    @Override
    public PlazaWorkReportDto.ReportListResponse getMyReports(Long userId, Integer page, Integer size) {
        if (page == null || page < 1) page = 1;
        if (size == null || size < 1) size = 10;
        if (size > 100) size = 100;
        
        int offset = (page - 1) * size;
        
        List<PlazaWorkReport> reports = reportMapper.selectByReporterId(userId, offset, size);
        Long total = reportMapper.countByReporterId(userId);
        
        List<PlazaWorkReportDto.ReportResponse> records = reports.stream()
                .map(this::convertToReportResponse)
                .collect(Collectors.toList());
        
        int totalPages = (int) Math.ceil((double) total / size);
        
        return PlazaWorkReportDto.ReportListResponse.builder()
                .records(records)
                .total(total)
                .page(page)
                .size(size)
                .totalPages(totalPages)
                .build();
    }

    @Override
    public PlazaWorkReportDto.AdminReportListResponse getAdminReportList(PlazaWorkReportDto.AdminReportQueryRequest request) {
        if (request.getPage() == null || request.getPage() < 1) request.setPage(1);
        if (request.getSize() == null || request.getSize() < 1) request.setSize(20);
        if (request.getSize() > 100) request.setSize(100);
        
        int offset = (request.getPage() - 1) * request.getSize();
        
        List<PlazaWorkReport> reports = reportMapper.selectAdminReportList(
                request.getReportStatus(),
                request.getReportType(),
                request.getWorkNo(),
                request.getReporterId(),
                offset,
                request.getSize()
        );
        
        Long total = reportMapper.countAdminReportList(
                request.getReportStatus(),
                request.getReportType(),
                request.getWorkNo(),
                request.getReporterId()
        );
        
        // 转换为管理员详情响应（需要关联作品信息）
        List<PlazaWorkReportDto.AdminReportDetailResponse> records = reports.stream()
                .map(this::convertToAdminReportDetailResponse)
                .collect(Collectors.toList());
        
        int totalPages = (int) Math.ceil((double) total / request.getSize());
        
        return PlazaWorkReportDto.AdminReportListResponse.builder()
                .records(records)
                .total(total)
                .page(request.getPage())
                .size(request.getSize())
                .totalPages(totalPages)
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditReport(Long adminId, String adminName, PlazaWorkReportDto.AuditReportRequest request) {
        log.info("管理员 {} 审核投诉，投诉编号: {}, 审核结果: {}", adminName, request.getReportNo(), request.getAuditStatus());
        
        // 1. 查询投诉记录
        PlazaWorkReport report = reportMapper.findByReportNo(request.getReportNo());
        if (report == null) {
            throw new IllegalArgumentException("投诉记录不存在: " + request.getReportNo());
        }
        
        if (!"pending".equals(report.getReportStatus())) {
            throw new IllegalArgumentException("该投诉已经审核过了");
        }
        
        // 2. 更新投诉审核信息
        report.setReportStatus(request.getAuditStatus());
        report.setAuditAdminId(adminId);
        report.setAuditAdminName(adminName);
        report.setAuditRemark(request.getAuditRemark());
        report.setAuditTime(LocalDateTime.now());
        
        reportMapper.updateAuditInfo(report);
        
        // 3. 如果投诉成立，下架作品（修改审核状态为 rejected）
        if ("approved".equals(request.getAuditStatus())) {
            PlazaWork work = plazaWorkMapper.findByWorkNo(report.getWorkNo());
            if (work != null) {
                // 更新作品审核状态为已拒绝，并隐藏作品
                work.setAuditStatus("rejected");
                work.setStatus("hidden");
                work.setAuditAdminId(adminId);
                work.setAuditTime(LocalDateTime.now());
                work.setAuditRemark("因投诉成立，作品已下架：" + (request.getAuditRemark() != null ? request.getAuditRemark() : ""));
                plazaWorkMapper.update(work);
                log.info("投诉成立，作品已下架，作品编号: {}", report.getWorkNo());
            }
        }
        
        log.info("投诉审核完成，投诉编号: {}", request.getReportNo());
        return true;
    }

    @Override
    public Long getPendingReportCount() {
        return reportMapper.countPendingReports();
    }

    /**
     * 检查投诉限制
     */
    private void checkReportLimit(Long userId) {
        LocalDate today = LocalDate.now();
        PlazaWorkReportLimit limit = limitMapper.findByUserId(userId);
        
        if (limit == null) {
            // 首次投诉，创建记录
            limit = PlazaWorkReportLimit.builder()
                    .userId(userId)
                    .reportCount(1)
                    .lastReportTime(LocalDateTime.now())
                    .resetDate(today)
                    .build();
            limitMapper.insertOrUpdate(limit);
            return;
        }
        
        // 检查是否需要重置（跨天）
        if (!today.equals(limit.getResetDate())) {
            limitMapper.resetReportCount(userId, today);
            limit.setReportCount(0);
            limit.setResetDate(today);
        }
        
        // 检查是否超过限制
        if (limit.getReportCount() >= MAX_REPORT_COUNT_PER_DAY) {
            throw new IllegalArgumentException("今日投诉次数已达上限（" + MAX_REPORT_COUNT_PER_DAY + "次），请明天再试");
        }
    }

    /**
     * 更新投诉限制计数
     */
    private void updateReportLimit(Long userId) {
        PlazaWorkReportLimit limit = limitMapper.findByUserId(userId);
        if (limit == null) {
            LocalDate today = LocalDate.now();
            limit = PlazaWorkReportLimit.builder()
                    .userId(userId)
                    .reportCount(1)
                    .lastReportTime(LocalDateTime.now())
                    .resetDate(today)
                    .build();
            limitMapper.insertOrUpdate(limit);
        } else {
            limitMapper.incrementReportCount(userId);
        }
    }

    /**
     * 生成投诉编号
     */
    private String generateReportNo() {
        java.util.Random random = new java.util.Random();
        return "REPORT-" + LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "-" + 
               String.format("%04d", random.nextInt(10000));
    }

    /**
     * 转换为投诉响应
     */
    private PlazaWorkReportDto.ReportResponse convertToReportResponse(PlazaWorkReport report) {
        return PlazaWorkReportDto.ReportResponse.builder()
                .reportNo(report.getReportNo())
                .workNo(report.getWorkNo())
                .reportType(report.getReportType())
                .reportTypeName(getReportTypeName(report.getReportType()))
                .reportReason(report.getReportReason())
                .reportStatus(report.getReportStatus())
                .reportStatusName(getReportStatusName(report.getReportStatus()))
                .createTime(report.getCreateTime())
                .build();
    }

    /**
     * 转换为管理员投诉详情响应
     */
    private PlazaWorkReportDto.AdminReportDetailResponse convertToAdminReportDetailResponse(PlazaWorkReport report) {
        // 查询作品信息
        PlazaWork work = plazaWorkMapper.findByWorkNo(report.getWorkNo());
        
        PlazaWorkReportDto.AdminReportDetailResponse.AdminReportDetailResponseBuilder builder = 
                PlazaWorkReportDto.AdminReportDetailResponse.builder()
                .reportNo(report.getReportNo())
                .workId(report.getWorkId())
                .workNo(report.getWorkNo())
                .reporterId(report.getReporterId())
                .reportType(report.getReportType())
                .reportTypeName(getReportTypeName(report.getReportType()))
                .reportReason(report.getReportReason())
                .reportStatus(report.getReportStatus())
                .reportStatusName(getReportStatusName(report.getReportStatus()))
                .auditAdminId(report.getAuditAdminId())
                .auditAdminName(report.getAuditAdminName())
                .auditRemark(report.getAuditRemark())
                .auditTime(report.getAuditTime())
                .createTime(report.getCreateTime());
        
        if (work != null) {
            builder.workTitle(work.getTitle())
                   .workResultUrl(work.getResultUrl());
        }
        
        // 查询投诉人用户名
        try {
            com.dora.entity.User reporter = userMapper.selectById(report.getReporterId());
            if (reporter != null) {
                builder.reporterUsername(reporter.getUsername());
            }
        } catch (Exception e) {
            log.warn("查询投诉人用户名失败: {}", e.getMessage());
        }
        
        return builder.build();
    }

    /**
     * 获取投诉类型名称
     */
    private String getReportTypeName(String reportType) {
        if (reportType == null) return "未知";
        switch (reportType) {
            case "political":
                return "政治敏感";
            case "pornographic":
                return "色情低俗";
            case "violent":
                return "暴力血腥";
            case "dangerous":
                return "危险行为";
            case "uncomfortable":
                return "引人不适";
            case "other":
                return "其他";
            default:
                return "未知";
        }
    }

    /**
     * 获取投诉状态名称
     */
    private String getReportStatusName(String reportStatus) {
        if (reportStatus == null) return "未知";
        switch (reportStatus) {
            case "pending":
                return "待审核";
            case "approved":
                return "投诉成立";
            case "rejected":
                return "投诉不成立";
            default:
                return "未知";
        }
    }
}

