package top.tqx.demo_1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.tqx.demo_1.entity.UserAnswer;
import top.tqx.demo_1.entity.WrongQuestionCollection;
import top.tqx.demo_1.mapper.UserAnswerMapper;
import top.tqx.demo_1.mapper.WrongQuestionCollectionMapper;

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

@Slf4j
@Component
public class WrongQuestionSyncValidator {

    @Autowired
    private UserAnswerMapper userAnswerMapper;

    @Autowired
    private WrongQuestionCollectionMapper wrongQuestionCollectionMapper;

    public ValidationResult validateSyncIntegrity(Long userId, String paperId, String sessionId) {
        ValidationResult result = new ValidationResult();
        result.setUserId(userId);
        result.setPaperId(paperId);
        result.setSessionId(sessionId);
        result.setValidationTime(LocalDateTime.now());

        List<ValidationIssue> issues = new ArrayList<>();

        LambdaQueryWrapper<UserAnswer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserAnswer::getUserId, userId);
        
        if (paperId != null && !paperId.isEmpty()) {
            queryWrapper.eq(UserAnswer::getPaperId, paperId);
        }
        if (sessionId != null && !sessionId.isEmpty()) {
            queryWrapper.eq(UserAnswer::getSessionId, sessionId);
        }

        List<UserAnswer> userAnswers = userAnswerMapper.selectList(queryWrapper);
        
        if (userAnswers.isEmpty()) {
            issues.add(new ValidationIssue("NO_ANSWERS", "未找到用户答题记录", "warn"));
            result.setIssues(issues);
            return result;
        }

        int totalCount = userAnswers.size();
        int correctCount = 0;
        int wrongCount = 0;
        int partialCount = 0;
        int unknownCount = 0;

        Set<String> paperIds = new HashSet<>();
        Set<String> sessionIds = new HashSet<>();
        Set<String> questionIds = new HashSet<>();

        List<String> missingQuestionIds = new ArrayList<>();
        List<String> missingPaperIds = new ArrayList<>();
        List<String> missingSessionIds = new ArrayList<>();

        for (UserAnswer answer : userAnswers) {
            paperIds.add(answer.getPaperId());
            sessionIds.add(answer.getSessionId());
            questionIds.add(answer.getQuestionId());

            if (answer.getQuestionId() == null || answer.getQuestionId().isEmpty()) {
                missingQuestionIds.add(String.valueOf(answer.getId()));
            }

            if (answer.getPaperId() == null || answer.getPaperId().isEmpty()) {
                missingPaperIds.add(String.valueOf(answer.getId()));
            }

            if (answer.getSessionId() == null || answer.getSessionId().isEmpty()) {
                missingSessionIds.add(String.valueOf(answer.getId()));
            }

            Integer isCorrect = answer.getIsCorrect();
            if (isCorrect == 1) {
                correctCount++;
            } else if (isCorrect == 0) {
                wrongCount++;
            } else if (isCorrect == 2) {
                partialCount++;
            } else {
                unknownCount++;
                issues.add(new ValidationIssue("UNKNOWN_IS_CORRECT", 
                        "答题记录ID " + answer.getId() + " 的isCorrect值未知: " + isCorrect, "warn"));
            }
        }

        if (!missingQuestionIds.isEmpty()) {
            issues.add(new ValidationIssue("MISSING_QUESTION_ID", 
                    "存在缺少question_id的答题记录: " + missingQuestionIds.size() + "条", "error"));
        }

        if (!missingPaperIds.isEmpty()) {
            issues.add(new ValidationIssue("MISSING_PAPER_ID", 
                    "存在缺少paper_id的答题记录: " + missingPaperIds.size() + "条", "warn"));
        }

        if (!missingSessionIds.isEmpty()) {
            issues.add(new ValidationIssue("MISSING_SESSION_ID", 
                    "存在缺少session_id的答题记录: " + missingSessionIds.size() + "条", "warn"));
        }

        if (unknownCount > 0) {
            issues.add(new ValidationIssue("INVALID_IS_CORRECT", 
                    "存在isCorrect值无效的答题记录: " + unknownCount + "条", "error"));
        }

        LambdaQueryWrapper<UserAnswer> wrongQuery = new LambdaQueryWrapper<>();
        wrongQuery.eq(UserAnswer::getUserId, userId);
        wrongQuery.and(w -> w.eq(UserAnswer::getIsCorrect, 0).or().eq(UserAnswer::getIsCorrect, 2));
        if (paperId != null && !paperId.isEmpty()) {
            wrongQuery.eq(UserAnswer::getPaperId, paperId);
        }
        int expectedWrongCount = userAnswerMapper.selectCount(wrongQuery).intValue();

        if (wrongCount + partialCount != expectedWrongCount) {
            issues.add(new ValidationIssue("WRONG_COUNT_MISMATCH", 
                    "错题统计不一致: 计算值=" + (wrongCount + partialCount) + ", 查询值=" + expectedWrongCount, "error"));
        }

        LambdaQueryWrapper<WrongQuestionCollection> collectionQuery = new LambdaQueryWrapper<>();
        collectionQuery.eq(WrongQuestionCollection::getUserId, userId);
        List<WrongQuestionCollection> collections = wrongQuestionCollectionMapper.selectList(collectionQuery);

        Set<Long> collectedAnswerIds = collections.stream()
                .map(WrongQuestionCollection::getAnswerId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        Set<Long> answerIds = userAnswers.stream()
                .map(UserAnswer::getId)
                .collect(Collectors.toSet());

        for (Long collectedId : collectedAnswerIds) {
            if (!answerIds.contains(collectedId)) {
                issues.add(new ValidationIssue("STALE_COLLECTION", 
                        "收藏记录引用了不存在的答题记录: answerId=" + collectedId, "error"));
            }
        }

        result.setTotalAnswers(totalCount);
        result.setCorrectCount(correctCount);
        result.setWrongCount(wrongCount);
        result.setPartialCount(partialCount);
        result.setUnknownCount(unknownCount);
        result.setCollectedCount(collections.size());
        result.setUniquePaperCount(paperIds.size());
        result.setUniqueSessionCount(sessionIds.size());
        result.setUniqueQuestionCount(questionIds.size());
        result.setIssues(issues);
        result.setSuccess(issues.stream().noneMatch(i -> "error".equals(i.getSeverity())));

        log.info("数据同步验证完成: userId={}, total={}, correct={}, wrong={}, partial={}, success={}",
                userId, totalCount, correctCount, wrongCount, partialCount, result.isSuccess());

        return result;
    }

    public ValidationResult validateAllUsers(int pageSize) {
        ValidationResult result = new ValidationResult();
        result.setValidationTime(LocalDateTime.now());
        result.setIssues(new ArrayList<>());

        LambdaQueryWrapper<UserAnswer> userQuery = new LambdaQueryWrapper<>();
        userQuery.select(UserAnswer::getUserId);
        userQuery.groupBy(UserAnswer::getUserId);
        
        List<Object> userIds = userAnswerMapper.selectObjs(userQuery);

        int totalUsers = userIds.size();
        int failedUsers = 0;
        int totalAnswers = 0;
        int totalWrong = 0;

        for (Object userIdObj : userIds) {
            Long userId = ((Number) userIdObj).longValue();
            ValidationResult userResult = validateSyncIntegrity(userId, null, null);
            
            totalAnswers += userResult.getTotalAnswers();
            totalWrong += userResult.getWrongCount() + userResult.getPartialCount();
            
            if (!userResult.isSuccess()) {
                failedUsers++;
                for (ValidationIssue issue : userResult.getIssues()) {
                    if ("error".equals(issue.getSeverity())) {
                        result.getIssues().add(new ValidationIssue(
                                issue.getCode(),
                                "用户 " + userId + ": " + issue.getMessage(),
                                issue.getSeverity()
                        ));
                    }
                }
            }
        }

        result.setTotalAnswers(totalAnswers);
        result.setWrongCount(totalWrong);
        result.setSuccess(failedUsers == 0);
        result.setMessage(String.format("共验证 %d 个用户, %d 条答题记录, %d 条错题, 失败 %d 个用户",
                totalUsers, totalAnswers, totalWrong, failedUsers));

        log.info("全量数据同步验证完成: users={}, totalAnswers={}, totalWrong={}, failedUsers={}",
                totalUsers, totalAnswers, totalWrong, failedUsers);

        return result;
    }

    public ValidationResult validateRecentAnswers(LocalDateTime startTime) {
        ValidationResult result = new ValidationResult();
        result.setValidationTime(LocalDateTime.now());
        result.setIssues(new ArrayList<>());

        LambdaQueryWrapper<UserAnswer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(UserAnswer::getCreatedAt, startTime);
        
        Page<UserAnswer> page = new Page<>(1, 1000);
        IPage<UserAnswer> iPage = userAnswerMapper.selectPage(page, queryWrapper);
        
        List<UserAnswer> recentAnswers = iPage.getRecords();
        
        int missingPaperId = 0;
        int missingSessionId = 0;
        int invalidIsCorrect = 0;

        for (UserAnswer answer : recentAnswers) {
            if (answer.getPaperId() == null || answer.getPaperId().isEmpty()) {
                missingPaperId++;
            }
            if (answer.getSessionId() == null || answer.getSessionId().isEmpty()) {
                missingSessionId++;
            }
            Integer isCorrect = answer.getIsCorrect();
            if (isCorrect == null || isCorrect < 0 || isCorrect > 2) {
                invalidIsCorrect++;
            }
        }

        if (missingPaperId > 0) {
            result.getIssues().add(new ValidationIssue("RECENT_MISSING_PAPER_ID",
                    "最近答题记录中缺少paper_id的数量: " + missingPaperId, "warn"));
        }

        if (missingSessionId > 0) {
            result.getIssues().add(new ValidationIssue("RECENT_MISSING_SESSION_ID",
                    "最近答题记录中缺少session_id的数量: " + missingSessionId, "warn"));
        }

        if (invalidIsCorrect > 0) {
            result.getIssues().add(new ValidationIssue("RECENT_INVALID_IS_CORRECT",
                    "最近答题记录中isCorrect值无效的数量: " + invalidIsCorrect, "error"));
        }

        result.setTotalAnswers((int) iPage.getTotal());
        result.setSuccess(result.getIssues().stream().noneMatch(i -> "error".equals(i.getSeverity())));
        result.setMessage(String.format("验证 %s 之后的 %d 条答题记录", startTime, iPage.getTotal()));

        return result;
    }

    public static class ValidationResult {
        private Long userId;
        private String paperId;
        private String sessionId;
        private LocalDateTime validationTime;
        private int totalAnswers;
        private int correctCount;
        private int wrongCount;
        private int partialCount;
        private int unknownCount;
        private int collectedCount;
        private int uniquePaperCount;
        private int uniqueSessionCount;
        private int uniqueQuestionCount;
        private boolean success;
        private String message;
        private List<ValidationIssue> issues;

        public ValidationResult() {
            this.issues = new ArrayList<>();
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public Long getUserId() { return userId; }
        public void setUserId(Long userId) { this.userId = userId; }
        public String getPaperId() { return paperId; }
        public void setPaperId(String paperId) { this.paperId = paperId; }
        public String getSessionId() { return sessionId; }
        public void setSessionId(String sessionId) { this.sessionId = sessionId; }
        public LocalDateTime getValidationTime() { return validationTime; }
        public void setValidationTime(LocalDateTime validationTime) { this.validationTime = validationTime; }
        public int getTotalAnswers() { return totalAnswers; }
        public void setTotalAnswers(int totalAnswers) { this.totalAnswers = totalAnswers; }
        public int getCorrectCount() { return correctCount; }
        public void setCorrectCount(int correctCount) { this.correctCount = correctCount; }
        public int getWrongCount() { return wrongCount; }
        public void setWrongCount(int wrongCount) { this.wrongCount = wrongCount; }
        public int getPartialCount() { return partialCount; }
        public void setPartialCount(int partialCount) { this.partialCount = partialCount; }
        public int getUnknownCount() { return unknownCount; }
        public void setUnknownCount(int unknownCount) { this.unknownCount = unknownCount; }
        public int getCollectedCount() { return collectedCount; }
        public void setCollectedCount(int collectedCount) { this.collectedCount = collectedCount; }
        public int getUniquePaperCount() { return uniquePaperCount; }
        public void setUniquePaperCount(int uniquePaperCount) { this.uniquePaperCount = uniquePaperCount; }
        public int getUniqueSessionCount() { return uniqueSessionCount; }
        public void setUniqueSessionCount(int uniqueSessionCount) { this.uniqueSessionCount = uniqueSessionCount; }
        public int getUniqueQuestionCount() { return uniqueQuestionCount; }
        public void setUniqueQuestionCount(int uniqueQuestionCount) { this.uniqueQuestionCount = uniqueQuestionCount; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public List<ValidationIssue> getIssues() { return issues; }
        public void setIssues(List<ValidationIssue> issues) { this.issues = issues; }
    }

    public static class ValidationIssue {
        private String code;
        private String message;
        private String severity;

        public ValidationIssue(String code, String message, String severity) {
            this.code = code;
            this.message = message;
            this.severity = severity;
        }

        public String getCode() { return code; }
        public void setCode(String code) { this.code = code; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public String getSeverity() { return severity; }
        public void setSeverity(String severity) { this.severity = severity; }
    }
}
