package com.dora.service.impl;

import com.dora.dto.AdminPlazaAuditDto.*;
import com.dora.entity.PlazaWork;
import com.dora.entity.PlazaWorkAuditLog;
import com.dora.entity.User;
import com.dora.mapper.PlazaWorkAuditLogMapper;
import com.dora.mapper.PlazaWorkMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.AdminPlazaAuditService;
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.ArrayList;
import java.util.List;

/**
 * 广场作品审核服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminPlazaAuditServiceImpl implements AdminPlazaAuditService {

    private final PlazaWorkMapper plazaWorkMapper;
    private final PlazaWorkAuditLogMapper auditLogMapper;
    private final UserMapper userMapper;

    @Override
    public PendingWorksListResponse getPendingWorks(PendingWorksQueryRequest request) {
        int page = request.getPage() != null && request.getPage() > 0 ? request.getPage() : 1;
        int size = request.getSize() != null && request.getSize() > 0 ? request.getSize() : 20;
        int offset = (page - 1) * size;

        // 查询待审核作品
        List<PlazaWork> works = plazaWorkMapper.selectPendingWorks(
                request.getTaskType(),
                request.getUserId(),
                offset,
                size
        );

        // 统计总数
        long total = plazaWorkMapper.countPendingWorks(
                request.getTaskType(),
                request.getUserId()
        );

        // 转换为DTO
        List<PendingWorkDetailResponse> workResponses = new ArrayList<>();
        for (PlazaWork work : works) {
            User author = userMapper.selectById(work.getUserId());
            PendingWorkDetailResponse response = convertToPendingWorkDetail(work, author);
            workResponses.add(response);
        }

        return PendingWorksListResponse.builder()
                .works(workResponses)
                .total(total)
                .page(page)
                .size(size)
                .totalPages((int) Math.ceil((double) total / size))
                .build();
    }

    @Override
    public PendingWorkDetailResponse getPendingWorkDetail(String workNo) {
        PlazaWork work = plazaWorkMapper.findByWorkNo(workNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在");
        }

        if (!"pending".equals(work.getAuditStatus())) {
            throw new IllegalArgumentException("该作品不是待审核状态");
        }

        User author = userMapper.selectById(work.getUserId());
        return convertToPendingWorkDetail(work, author);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AuditResultResponse auditWork(AuditWorkRequest request, Long adminId, String adminName) {
        String workNo = request.getWorkNo();
        String auditStatus = request.getAuditStatus();
        String auditRemark = request.getAuditRemark();

        // 验证审核状态
        if (!"approved".equals(auditStatus) && !"rejected".equals(auditStatus)) {
            throw new IllegalArgumentException("审核状态只能是 approved 或 rejected");
        }

        // 如果拒绝，必须填写备注
        if ("rejected".equals(auditStatus) && (auditRemark == null || auditRemark.trim().isEmpty())) {
            throw new IllegalArgumentException("拒绝审核时必须填写备注说明原因");
        }

        // 查询作品
        PlazaWork work = plazaWorkMapper.findByWorkNo(workNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在");
        }

        if (!"pending".equals(work.getAuditStatus())) {
            throw new IllegalArgumentException("该作品已审核，不能重复审核");
        }

        LocalDateTime auditTime = LocalDateTime.now();

        // 更新作品审核状态
        work.setAuditStatus(auditStatus);
        work.setAuditAdminId(adminId);
        work.setAuditTime(auditTime);
        work.setAuditRemark(auditRemark);
        work.setUpdateTime(auditTime);
        plazaWorkMapper.updateById(work);

        // 记录审核日志
        PlazaWorkAuditLog auditLog = new PlazaWorkAuditLog();
        auditLog.setWorkNo(workNo);
        auditLog.setWorkId(work.getId());
        auditLog.setAuditStatus(auditStatus);
        auditLog.setAuditAdminId(adminId);
        auditLog.setAuditAdminName(adminName);
        auditLog.setAuditRemark(auditRemark);
        auditLog.setAuditTime(auditTime);
        auditLogMapper.insert(auditLog);

        log.info("作品审核完成 - workNo: {}, auditStatus: {}, adminId: {}, adminName: {}",
                workNo, auditStatus, adminId, adminName);

        return AuditResultResponse.builder()
                .workNo(workNo)
                .auditStatus(auditStatus)
                .auditTime(auditTime)
                .auditAdminId(adminId)
                .auditRemark(auditRemark)
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchAuditWorks(List<String> workNos, String auditStatus, String auditRemark, Long adminId, String adminName) {
        if (workNos == null || workNos.isEmpty()) {
            return 0;
        }

        int successCount = 0;
        for (String workNo : workNos) {
            try {
                AuditWorkRequest request = new AuditWorkRequest();
                request.setWorkNo(workNo);
                request.setAuditStatus(auditStatus);
                request.setAuditRemark(auditRemark);
                auditWork(request, adminId, adminName);
                successCount++;
            } catch (Exception e) {
                log.error("批量审核失败 - workNo: {}, error: {}", workNo, e.getMessage());
            }
        }

        return successCount;
    }

    @Override
    public AuditStatsResponse getAuditStats() {
        // 待审核数量
        long pendingCount = plazaWorkMapper.countPendingWorks(null, null);

        // 今日审核通过数量
        long todayApprovedCount = auditLogMapper.countTodayApproved();

        // 今日审核拒绝数量
        long todayRejectedCount = auditLogMapper.countTodayRejected();

        // 总审核数量
        long totalAuditedCount = auditLogMapper.countTotal();

        return AuditStatsResponse.builder()
                .pendingCount(pendingCount)
                .todayApprovedCount(todayApprovedCount)
                .todayRejectedCount(todayRejectedCount)
                .totalAuditedCount(totalAuditedCount)
                .build();
    }

    @Override
    public List<AuditHistoryRecord> getAuditHistory(AuditHistoryQueryRequest request) {
        int page = request.getPage() != null && request.getPage() > 0 ? request.getPage() : 1;
        int size = request.getSize() != null && request.getSize() > 0 ? request.getSize() : 20;
        int offset = (page - 1) * size;

        List<PlazaWorkAuditLog> logs = auditLogMapper.selectAuditHistory(
                request.getAuditStatus(),
                request.getAuditAdminId(),
                request.getStartTime(),
                request.getEndTime(),
                offset,
                size
        );

        List<AuditHistoryRecord> records = new ArrayList<>();
        for (PlazaWorkAuditLog log : logs) {
            PlazaWork work = plazaWorkMapper.findByWorkNo(log.getWorkNo());
            AuditHistoryRecord record = AuditHistoryRecord.builder()
                    .id(log.getId())
                    .workNo(log.getWorkNo())
                    .workTitle(work != null ? work.getTitle() : "未知作品")
                    .auditStatus(log.getAuditStatus())
                    .auditAdminId(log.getAuditAdminId())
                    .auditAdminName(log.getAuditAdminName())
                    .auditRemark(log.getAuditRemark())
                    .auditTime(log.getAuditTime())
                    .build();
            records.add(record);
        }

        return records;
    }

    @Override
    @Transactional
    public AuditResultResponse revokeAudit(String workNo, String reason, Long adminId, String adminName) {
        log.info("撤销审核，workNo: {}, adminId: {}, reason: {}", workNo, adminId, reason);

        // 1. 查询作品
        PlazaWork work = plazaWorkMapper.findByWorkNo(workNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在");
        }

        // 2. 只能撤销已审核的作品
        if ("pending".equals(work.getAuditStatus())) {
            throw new IllegalArgumentException("该作品尚未审核，无需撤销");
        }

        // 3. 更新为待审核状态
        work.setAuditStatus("pending");
        work.setAuditAdminId(null);
        work.setAuditTime(null);
        work.setAuditRemark("审核已撤销：" + reason);
        work.setUpdateTime(LocalDateTime.now());
        plazaWorkMapper.updateById(work);

        // 4. 记录审核日志
        PlazaWorkAuditLog auditLog = new PlazaWorkAuditLog();
        auditLog.setWorkNo(workNo);
        auditLog.setWorkId(work.getId());
        auditLog.setAuditStatus("revoked");
        auditLog.setAuditAdminId(adminId);
        auditLog.setAuditAdminName(adminName);
        auditLog.setAuditRemark("撤销审核：" + reason);
        auditLog.setAuditTime(LocalDateTime.now());
        auditLogMapper.insert(auditLog);

        log.info("审核撤销成功，workNo: {}", workNo);

        return AuditResultResponse.builder()
                .workNo(workNo)
                .auditStatus("pending")
                .auditTime(LocalDateTime.now())
                .auditAdminId(adminId)
                .auditRemark("已撤销，原因：" + reason)
                .build();
    }

    @Override
    @Transactional
    public int quickApprove(int count, String taskType, Long adminId, String adminName) {
        log.info("快捷审核，count: {}, taskType: {}, adminId: {}", count, taskType, adminId);

        // 1. 查询最早的N个待审核作品
        List<PlazaWork> works = plazaWorkMapper.findEarliestPendingWorks(count, taskType);

        int successCount = 0;
        for (PlazaWork work : works) {
            try {
                // 2. 更新为已通过
                work.setAuditStatus("approved");
                work.setAuditAdminId(adminId);
                work.setAuditTime(LocalDateTime.now());
                work.setAuditRemark("快捷审核通过");
                work.setUpdateTime(LocalDateTime.now());
                plazaWorkMapper.updateById(work);

                // 3. 记录审核日志
                PlazaWorkAuditLog auditLog = new PlazaWorkAuditLog();
                auditLog.setWorkNo(work.getWorkNo());
                auditLog.setWorkId(work.getId());
                auditLog.setAuditStatus("approved");
                auditLog.setAuditAdminId(adminId);
                auditLog.setAuditAdminName(adminName);
                auditLog.setAuditRemark("快捷审核通过");
                auditLog.setAuditTime(LocalDateTime.now());
                auditLogMapper.insert(auditLog);

                successCount++;
            } catch (Exception e) {
                log.error("快捷审核失败，workNo: {}, error: {}", work.getWorkNo(), e.getMessage());
            }
        }

        log.info("快捷审核完成，成功: {}/{}", successCount, works.size());
        return successCount;
    }

    @Override
    public WorkAuditDetailResponse getWorkAuditDetail(String workNo) {
        log.info("查询作品详细审核信息，workNo: {}", workNo);

        // 1. 查询作品基本信息
        PlazaWork work = plazaWorkMapper.findByWorkNo(workNo);
        if (work == null) {
            throw new IllegalArgumentException("作品不存在");
        }

        // 2. 查询作者信息
        User author = userMapper.selectById(work.getUserId());

        // 3. 查询审核历史
        List<PlazaWorkAuditLog> auditLogs = auditLogMapper.findByWorkNo(workNo);
        List<AuditHistoryRecord> historyRecords = new ArrayList<>();
        for (PlazaWorkAuditLog log : auditLogs) {
            historyRecords.add(AuditHistoryRecord.builder()
                    .id(log.getId())
                    .workNo(log.getWorkNo())
                    .workTitle(work.getTitle())
                    .auditStatus(log.getAuditStatus())
                    .auditAdminId(log.getAuditAdminId())
                    .auditAdminName(log.getAuditAdminName())
                    .auditRemark(log.getAuditRemark())
                    .auditTime(log.getAuditTime())
                    .build());
        }

        // 4. 查询作者统计信息
        java.util.Map<String, Object> authorStats = plazaWorkMapper.getAuthorStats(work.getUserId());
        long total = ((Number) authorStats.getOrDefault("total", 0L)).longValue();
        long approved = ((Number) authorStats.getOrDefault("approved", 0L)).longValue();
        double approvalRate = total > 0 ? (approved * 100.0 / total) : 0.0;

        // 5. 构建响应
        PendingWorkDetailResponse workInfo = convertToPendingWorkDetail(work, author);

        return WorkAuditDetailResponse.builder()
                .workInfo(workInfo)
                .auditStatus(work.getAuditStatus())
                .auditRemark(work.getAuditRemark())
                .auditTime(work.getAuditTime())
                .auditAdminName(work.getAuditAdminId() != null ? 
                        auditLogs.isEmpty() ? "未知" : auditLogs.get(0).getAuditAdminName() : null)
                .auditHistory(historyRecords)
                .authorApprovalRate(approvalRate)
                .authorTotalWorks((int) total)
                .build();
    }

    @Override
    public AdminWorkloadStatsResponse getAdminWorkloadStats(Long adminId, String startTime, String endTime) {
        log.info("查询审核员工作量统计，adminId: {}, startTime: {}, endTime: {}", adminId, startTime, endTime);

        // 1. 查询基础统计数据
        java.util.Map<String, Object> stats = auditLogMapper.getAdminStats(adminId, startTime, endTime);
        
        long totalAudited = ((Number) stats.getOrDefault("total_audited", 0L)).longValue();
        long approvedCount = ((Number) stats.getOrDefault("approved_count", 0L)).longValue();
        long rejectedCount = ((Number) stats.getOrDefault("rejected_count", 0L)).longValue();
        
        Double avgMinutes = stats.get("avg_audit_minutes") != null ? 
                ((Number) stats.get("avg_audit_minutes")).doubleValue() : 0.0;

        double approvalRate = totalAudited > 0 ? (approvedCount * 100.0 / totalAudited) : 0.0;

        // 2. 查询最忙碌日期
        java.util.Map<String, Object> busiestDate = auditLogMapper.getBusiestDate(adminId, startTime, endTime);
        String busiestDateStr = busiestDate != null && busiestDate.get("date") != null ? 
                busiestDate.get("date").toString() : null;
        Long busiestDateCount = busiestDate != null && busiestDate.get("count") != null ? 
                ((Number) busiestDate.get("count")).longValue() : 0L;

        // 3. 查询管理员名称（从最近的审核记录中获取）
        List<PlazaWorkAuditLog> recentLogs = auditLogMapper.selectAuditHistory(null, adminId, null, null, 0, 1);
        String adminName = !recentLogs.isEmpty() ? recentLogs.get(0).getAuditAdminName() : "未知";

        return AdminWorkloadStatsResponse.builder()
                .adminId(adminId)
                .adminName(adminName)
                .startTime(startTime)
                .endTime(endTime)
                .totalAudited(totalAudited)
                .approvedCount(approvedCount)
                .rejectedCount(rejectedCount)
                .approvalRate(approvalRate)
                .avgAuditTimeMinutes(avgMinutes)
                .busiestDate(busiestDateStr)
                .busiestDateCount(busiestDateCount)
                .build();
    }

    /**
     * 转换为待审核作品详情DTO
     */
    private PendingWorkDetailResponse convertToPendingWorkDetail(PlazaWork work, User author) {
        PendingWorkDetailResponse.AuthorInfo authorInfo = null;
        if (author != null) {
            authorInfo = PendingWorkDetailResponse.AuthorInfo.builder()
                    .userId(author.getId())
                    .username(author.getUsername())
                    .phone(author.getPhone())
                    .avatarUrl(author.getAvatarUrl())
                    .build();
        }

        return PendingWorkDetailResponse.builder()
                .workNo(work.getWorkNo())
                .title(work.getTitle())
                .description(work.getDescription())
                .coverUrl(work.getResultUrl())
                .resultUrl(work.getResultUrl())
                .taskType(work.getTaskType())
                .modelName(work.getModelName())
                .prompt(work.getPrompt())
                .createTime(work.getCreateTime())
                .author(authorInfo)
                .taskNo(work.getTaskNo())
                .build();
    }
}

