package com.competition.modules.pub.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.competition.common.exception.BusinessException;
import com.competition.common.result.PageResult;
import com.competition.modules.sys.entity.SysUser;
import com.competition.modules.sys.mapper.SysUserMapper;
import com.competition.modules.ugc.entity.UgcReviewLog;
import com.competition.modules.ugc.entity.UgcWork;
import com.competition.modules.ugc.mapper.UgcReviewLogMapper;
import com.competition.modules.ugc.mapper.UgcWorkMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class PublicContentReviewService {

    private final UgcWorkMapper ugcWorkMapper;
    private final UgcReviewLogMapper ugcReviewLogMapper;
    private final SysUserMapper sysUserMapper;

    /**
     * 获取各状态统计
     */
    public Map<String, Long> getStats() {
        Map<String, Long> stats = new LinkedHashMap<>();
        stats.put("pending_review", countByStatus("pending_review"));
        stats.put("published", countByStatus("published"));
        stats.put("rejected", countByStatus("rejected"));
        stats.put("taken_down", countByStatus("taken_down"));
        return stats;
    }

    /**
     * 获取待审核作品队列
     */
    public PageResult<Map<String, Object>> getWorkQueue(int page, int pageSize, String status,
                                                         String keyword, String startTime, String endTime,
                                                         String sortBy, Boolean isRecommended) {
        LambdaQueryWrapper<UgcWork> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UgcWork::getIsDeleted, 0);
        if (StringUtils.hasText(status)) {
            wrapper.eq(UgcWork::getStatus, status);
        }
        if (StringUtils.hasText(keyword)) {
            wrapper.like(UgcWork::getTitle, keyword);
        }
        if (StringUtils.hasText(startTime)) {
            wrapper.ge(UgcWork::getCreateTime, LocalDateTime.parse(startTime));
        }
        if (StringUtils.hasText(endTime)) {
            wrapper.le(UgcWork::getCreateTime, LocalDateTime.parse(endTime));
        }
        if (isRecommended != null) {
            wrapper.eq(UgcWork::getIsRecommended, isRecommended);
        }

        if ("oldest".equals(sortBy)) {
            wrapper.orderByAsc(UgcWork::getCreateTime);
        } else {
            wrapper.orderByDesc(UgcWork::getCreateTime);
        }

        IPage<UgcWork> result = ugcWorkMapper.selectPage(new Page<>(page, pageSize), wrapper);

        List<Map<String, Object>> voList = new ArrayList<>();
        for (UgcWork work : result.getRecords()) {
            Map<String, Object> vo = buildReviewWorkVo(work);
            voList.add(vo);
        }
        return PageResult.from(result, voList);
    }

    /**
     * 获取作品详情（审核用）
     */
    public Map<String, Object> getWorkDetail(Long id) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        return buildReviewWorkVo(work);
    }

    /**
     * 通过审核
     */
    @Transactional
    public void approve(Long id, String note, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        work.setStatus(3); // 3=COMPLETED/PUBLISHED
        work.setReviewNote(note);
        work.setReviewerId(operatorId);
        work.setReviewTime(LocalDateTime.now());
        work.setPublishTime(LocalDateTime.now());
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, "approve", null, note, operatorId);
    }

    /**
     * 驳回
     */
    @Transactional
    public void reject(Long id, String reason, String note, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        work.setStatus(-1); // -1=FAILED/REJECTED
        work.setReviewNote(note);
        work.setReviewerId(operatorId);
        work.setReviewTime(LocalDateTime.now());
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, "reject", reason, note, operatorId);
    }

    /**
     * 批量通过
     */
    @Transactional
    public void batchApprove(List<Long> ids, Long operatorId) {
        for (Long id : ids) {
            approve(id, null, operatorId);
        }
    }

    /**
     * 批量驳回
     */
    @Transactional
    public void batchReject(List<Long> ids, String reason, Long operatorId) {
        for (Long id : ids) {
            reject(id, reason, null, operatorId);
        }
    }

    /**
     * 撤回审核
     */
    @Transactional
    public void revoke(Long id, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        work.setStatus(1); // 1=PENDING
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, "revoke", null, null, operatorId);
    }

    /**
     * 下架
     */
    @Transactional
    public void takedown(Long id, String reason, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        work.setStatus(-2); // -2=TAKEN_DOWN
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, "takedown", reason, null, operatorId);
    }

    /**
     * 恢复
     */
    @Transactional
    public void restore(Long id, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        work.setStatus(3); // 3=COMPLETED/PUBLISHED
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, "restore", null, null, operatorId);
    }

    /**
     * 切换推荐状态
     */
    @Transactional
    public Map<String, Object> toggleRecommend(Long id, Long operatorId) {
        UgcWork work = ugcWorkMapper.selectById(id);
        if (work == null) {
            throw new BusinessException(404, "作品不存在");
        }
        boolean newState = !Boolean.TRUE.equals(work.getIsRecommended());
        work.setIsRecommended(newState);
        work.setModifyTime(LocalDateTime.now());
        ugcWorkMapper.updateById(work);
        createLog(id, newState ? "recommend" : "unrecommend", null, null, operatorId);

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("isRecommended", newState);
        return result;
    }

    /**
     * 管理概览统计
     */
    public Map<String, Object> getManagementStats() {
        Map<String, Object> stats = new LinkedHashMap<>();
        stats.put("total", ugcWorkMapper.selectCount(
                new LambdaQueryWrapper<UgcWork>().eq(UgcWork::getIsDeleted, 0)));
        stats.put("pendingReview", countByStatus("pending_review"));
        stats.put("published", countByStatus("published"));
        stats.put("rejected", countByStatus("rejected"));
        stats.put("takenDown", countByStatus("taken_down"));
        stats.put("recommended", ugcWorkMapper.selectCount(
                new LambdaQueryWrapper<UgcWork>()
                        .eq(UgcWork::getIsDeleted, 0)
                        .eq(UgcWork::getIsRecommended, true)));
        return stats;
    }

    /**
     * 获取审核日志
     */
    public PageResult<UgcReviewLog> getLogs(int page, int pageSize, Long workId) {
        LambdaQueryWrapper<UgcReviewLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UgcReviewLog::getTargetType, "work");
        if (workId != null) {
            wrapper.eq(UgcReviewLog::getWorkId, workId);
        }
        wrapper.orderByDesc(UgcReviewLog::getCreateTime);

        IPage<UgcReviewLog> result = ugcReviewLogMapper.selectPage(new Page<>(page, pageSize), wrapper);
        return PageResult.from(result);
    }

    private long countByStatus(String status) {
        return ugcWorkMapper.selectCount(
                new LambdaQueryWrapper<UgcWork>()
                        .eq(UgcWork::getIsDeleted, 0)
                        .eq(UgcWork::getStatus, status));
    }

    private void createLog(Long workId, String action, String reason, String note, Long operatorId) {
        UgcReviewLog logEntry = new UgcReviewLog();
        logEntry.setTargetType("work");
        logEntry.setTargetId(workId);
        logEntry.setWorkId(workId);
        logEntry.setAction(action);
        logEntry.setReason(reason);
        logEntry.setNote(note);
        logEntry.setOperatorId(operatorId);
        logEntry.setCreateTime(LocalDateTime.now());
        ugcReviewLogMapper.insert(logEntry);
    }

    private Map<String, Object> buildReviewWorkVo(UgcWork work) {
        Map<String, Object> vo = new LinkedHashMap<>();
        vo.put("id", work.getId());
        vo.put("title", work.getTitle());
        vo.put("coverUrl", work.getCoverUrl());
        vo.put("description", work.getDescription());
        vo.put("status", work.getStatus());
        vo.put("visibility", work.getVisibility());
        vo.put("isRecommended", work.getIsRecommended());
        vo.put("viewCount", work.getViewCount());
        vo.put("likeCount", work.getLikeCount());
        vo.put("favoriteCount", work.getFavoriteCount());
        vo.put("reviewNote", work.getReviewNote());
        vo.put("reviewTime", work.getReviewTime());
        vo.put("publishTime", work.getPublishTime());
        vo.put("createTime", work.getCreateTime());

        // 补充作者信息
        if (work.getUserId() != null) {
            SysUser user = sysUserMapper.selectById(work.getUserId());
            if (user != null) {
                Map<String, Object> userInfo = new LinkedHashMap<>();
                userInfo.put("id", user.getId());
                userInfo.put("username", user.getUsername());
                userInfo.put("nickname", user.getNickname());
                userInfo.put("avatar", user.getAvatar());
                vo.put("user", userInfo);
            }
        }
        return vo;
    }
}
