package com.seer.teach.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.admin.convert.RichTextTemplateConvert;
import com.seer.teach.admin.request.AdminConvertQuestionToHtmlReq;
import com.seer.teach.admin.request.BankQuestionsQueryReq;
import com.seer.teach.admin.request.ExampleQuestionsQueryReq;
import com.seer.teach.admin.request.QuestionPreviewReq;
import com.seer.teach.admin.request.RichTextTemplatePageReq;
import com.seer.teach.admin.request.RichTextTemplateQueryReq;
import com.seer.teach.admin.request.RichTextTemplateReq;
import com.seer.teach.admin.response.BankOptionsResp;
import com.seer.teach.admin.response.BankQuestionsResp;
import com.seer.teach.admin.response.ExampleQuestionsResp;
import com.seer.teach.admin.response.QuestionOptionsResp;
import com.seer.teach.admin.response.RichTextTemplateResp;
import com.seer.teach.admin.service.AdminBankQuestionsService;
import com.seer.teach.admin.service.AdminExampleQuestionsService;
import com.seer.teach.admin.service.AdminRichTextTemplateService;
import com.seer.teach.admin.util.RichTextTemplateProcessor;
import com.seer.teach.common.PageListBean;
import com.seer.teach.common.enums.QuestionTypesEnums;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.PageConverterUtils;
import com.seer.teach.teacher.module.entity.BankOptionsEntity;
import com.seer.teach.teacher.module.entity.BankQuestionsEntity;
import com.seer.teach.teacher.module.entity.ExampleQuestionsEntity;
import com.seer.teach.teacher.module.entity.RichTextTemplateEntity;
import com.seer.teach.teacher.service.BankOptionsService;
import com.seer.teach.teacher.service.BankQuestionsService;
import com.seer.teach.teacher.service.ExampleQuestionsService;
import com.seer.teach.teacher.service.IRichTextTemplateService;
import freemarker.template.TemplateException;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 富文本模板服务实现类
 *
 * @author ZS
 * @since 2025-10-30
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AdminRichTextTemplateServiceImpl implements AdminRichTextTemplateService {

    private final IRichTextTemplateService richTextTemplateService;
    private final RichTextTemplateProcessor richTextTemplateProcessor;
    private final AdminExampleQuestionsService adminExampleQuestionsService;
    private final ExampleQuestionsService exampleQuestionsService;
    private final BankQuestionsService bankQuestionsService;
    private final BankOptionsService bankOptionsService;

    public PageListBean<RichTextTemplateResp> pageList(RichTextTemplatePageReq pageRequest) {
        log.info("分页查询富文本模板列表，请求参数: {}", pageRequest);
        IPage<RichTextTemplateEntity> page = new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize());

        IPage<RichTextTemplateEntity> result = richTextTemplateService.page(page, new LambdaQueryWrapper<RichTextTemplateEntity>()
                .eq(StringUtils.hasText(pageRequest.getTemplateName()), RichTextTemplateEntity::getTemplateName, pageRequest.getTemplateName())
                .eq(Objects.nonNull(pageRequest.getTemplateType()), RichTextTemplateEntity::getTemplateType, pageRequest.getTemplateType())
                .eq(Objects.nonNull(pageRequest.getIsActive()), RichTextTemplateEntity::getIsActive, pageRequest.getIsActive())
        );

        log.info("分页查询富文本模板列表完成，查询到 {} 条记录", result.getRecords().size());
        return PageConverterUtils.convertPageListBean(result, RichTextTemplateConvert.INSTANCE::entityListToResponseList);
    }


    public List<RichTextTemplateResp> list(RichTextTemplateQueryReq queryParam) {
        log.info("查询富文本模板列表，请求参数: {}", queryParam);
        List<RichTextTemplateEntity> result = richTextTemplateService.list(new LambdaQueryWrapper<RichTextTemplateEntity>()
                .eq(Objects.nonNull(queryParam.getId()), RichTextTemplateEntity::getId, queryParam.getId())
                .eq(Objects.nonNull(queryParam.getTemplateName()), RichTextTemplateEntity::getTemplateName, queryParam.getTemplateName())
                .eq(Objects.nonNull(queryParam.getTemplateType()), RichTextTemplateEntity::getTemplateType, queryParam.getTemplateType())
                .eq(Objects.nonNull(queryParam.getIsActive()), RichTextTemplateEntity::getIsActive, queryParam.getIsActive())
                .eq(Objects.nonNull(queryParam.getVersion()), RichTextTemplateEntity::getVersion, queryParam.getVersion())
        );
        log.info("查询富文本模板列表完成，查询到 {} 条记录", result.size());
        return RichTextTemplateConvert.INSTANCE.entityListToResponseList(result);
    }

    @Override
    public RichTextTemplateResp getDetail(Integer id) {
        RichTextTemplateEntity entity = richTextTemplateService.getById(id);
        return RichTextTemplateConvert.INSTANCE.entityToResponse(entity);
    }

    @Override
    public Boolean save(RichTextTemplateReq requestParam) {
        RichTextTemplateEntity entity = RichTextTemplateConvert.INSTANCE.reqToEntity(requestParam);
        return richTextTemplateService.save(entity);
    }

    @Override
    public Boolean updateById(RichTextTemplateReq requestParam) {
        RichTextTemplateEntity entity = RichTextTemplateConvert.INSTANCE.reqToEntity(requestParam);
        return richTextTemplateService.updateById(entity);
    }

    @Override
    public Boolean deleteById(Integer id) {
        return richTextTemplateService.removeById(id);
    }

    @Override
    public String preview(QuestionPreviewReq requestParam) {
        try {
            return richTextTemplateProcessor.processTemplate(requestParam);
        } catch (IOException | TemplateException e) {
            log.error("预览题目时发生错误", e);
            throw new CommonException(ResultCodeEnum.RICH_TEXT_TEMPLATE_PREVIEW_FAILED, "预览失败: " + e.getMessage());
        }
    }

    @Override
    public String convertToHtml(QuestionPreviewReq requestParam) {
        try {
            return richTextTemplateProcessor.processTemplate(requestParam);
        } catch (IOException | TemplateException e) {
            log.error("转换题目为富文本时发生错误", e);
            throw new CommonException(ResultCodeEnum.RICH_TEXT_TEMPLATE_CONVERT_FAILED, "转换失败: " + e.getMessage());
        }
    }

    @Override
    public String convertAllExampleQuestionsToHtmlById(Integer id, AdminConvertQuestionToHtmlReq convertQuestionToHtmlReq) {
        RichTextTemplateEntity textTemplate = richTextTemplateService.getById(id);
        if (textTemplate == null) {
            log.warn("未找到ID为{}的富文本模板", id);
            return "未找到该模板";
        }

        try {
            // 根据类型处理题目转换
            if (1 == convertQuestionToHtmlReq.getType()) {
                // 处理示例题目
                ConversionStats stats = processAllExampleQuestions(textTemplate, convertQuestionToHtmlReq);
                return buildResultMessage(stats);
            } else {
                // 处理题库题目
                ConversionStats stats = processAllBankQuestions(textTemplate, convertQuestionToHtmlReq);
                return buildResultMessage(stats);
            }
        } catch (Exception e) {
            log.error("批量转换题目为HTML时发生错误", e);
            return "处理过程中发生错误: " + e.getMessage();
        }
    }

    /**
     * 处理所有示例题目
     */
    private ConversionStats processAllExampleQuestions(RichTextTemplateEntity textTemplate, 
                                                     AdminConvertQuestionToHtmlReq convertQuestionToHtmlReq) {
        ConversionStats stats = new ConversionStats();
        int currentPage = convertQuestionToHtmlReq.getPageNo();
        ProcessResult result;
        
        // 循环处理所有分页数据
        do {
            result = processExampleQuestionsPage(textTemplate, convertQuestionToHtmlReq, currentPage);
            stats.update(result);
            currentPage++;
            convertQuestionToHtmlReq.setPageNo(currentPage);
        } while (result.hasMoreData);
        
        return stats;
    }

    /**
     * 处理所有题库题目
     */
    private ConversionStats processAllBankQuestions(RichTextTemplateEntity textTemplate,
                                                  AdminConvertQuestionToHtmlReq convertQuestionToHtmlReq) {
        ConversionStats stats = new ConversionStats();
        int currentPage = convertQuestionToHtmlReq.getPageNo();
        ProcessResult result;
        
        // 循环处理所有分页数据
        do {
            result = processBankQuestionsPage(textTemplate, convertQuestionToHtmlReq, currentPage);
            stats.update(result);
            currentPage++;
            convertQuestionToHtmlReq.setPageNo(currentPage);
        } while (result.hasMoreData);
        
        return stats;
    }

    /**
     * 构建结果消息
     */
    private String buildResultMessage(ConversionStats stats) {
        log.info("批量转换完成，总共{}条记录，成功{}条，失败{}条", stats.totalCount, stats.successCount, stats.failureCount);
        return String.format("共处理 %d 条题目，成功 %d 条，失败 %d 条",
                stats.totalCount, stats.successCount, stats.failureCount);
    }

    /**
     * 处理示例题目页面
     */
    private ProcessResult processExampleQuestionsPage(RichTextTemplateEntity textTemplate, 
                                                     AdminConvertQuestionToHtmlReq convertQuestionToHtmlReq, 
                                                     int currentPage) {
        // 分页查询示例题目
        ExampleQuestionsQueryReq req = new ExampleQuestionsQueryReq();
        req.setPageNo(currentPage);
        req.setPageSize(convertQuestionToHtmlReq.getPageSize());
        req.setType(convertQuestionToHtmlReq.getQuestionType());
        IPage<ExampleQuestionsResp> result = adminExampleQuestionsService.pageExampleQuestions(req);

        // 如果没有数据则退出循环
        if (CollectionUtils.isEmpty(result.getRecords())) {
            return new ProcessResult(0L, 0, 0, false);
        }

        // 更新总记录数
        long totalCount = result.getTotal();
        log.info("开始处理第{}页示例题目，共{}条记录", currentPage, result.getRecords().size());

        List<ExampleQuestionsEntity> exampleQuestions = new ArrayList<>();
        int successCount = 0;
        int failureCount = 0;

        // 处理当前页的数据
        for (ExampleQuestionsResp questionsResp : result.getRecords()) {
            try {
                QuestionPreviewReq requestParam = buildQuestionPreviewReq(questionsResp);
                // 调用 processTemplate 方法获取 HTML 内容
                String htmlContent = richTextTemplateProcessor.processTemplate(textTemplate, requestParam);
                ExampleQuestionsEntity question = new ExampleQuestionsEntity();
                question.setId(questionsResp.getId());
                // 更新示例题目的 HTML 内容
                question.setHtml(htmlContent);
                exampleQuestions.add(question);
                successCount++;
            } catch (Exception e) {
                log.error("处理示例题目 ID={} 时出错", questionsResp.getId(), e);
                failureCount++;
            }
        }

        if (CollectionUtil.isNotEmpty(exampleQuestions)) {
            boolean updated = exampleQuestionsService.updateBatchById(exampleQuestions);
            log.info("更新{}条示例题目记录结果：{}", exampleQuestions.size(), updated);
        }

        boolean hasMoreData = currentPage < result.getPages();
        return new ProcessResult(totalCount, successCount, failureCount, hasMoreData);
    }

    /**
     * 处理题库题目页面
     */
    private ProcessResult processBankQuestionsPage(RichTextTemplateEntity textTemplate,
                                                  AdminConvertQuestionToHtmlReq convertQuestionToHtmlReq,
                                                  int currentPage) {
        // 分页查询题库题目
        IPage<BankQuestionsEntity> bankQuestionsPage = bankQuestionsService.selectPage(currentPage,convertQuestionToHtmlReq.getPageSize(),convertQuestionToHtmlReq.getQuestionType());
        List<BankQuestionsEntity> records = bankQuestionsPage.getRecords();
        // 如果没有数据则退出循环
        if (CollectionUtils.isEmpty(records)) {
            return new ProcessResult(0L, 0, 0, false);
        }

        // 更新总记录数
        long totalCount = bankQuestionsPage.getTotal();
        log.info("开始处理第{}页题库题目，共{}条记录", currentPage, bankQuestionsPage.getRecords().size());
        Set<Integer> bankQuestionIds = records.stream().map(BankQuestionsEntity::getId).collect(Collectors.toSet());
        List<BankOptionsEntity> options = bankOptionsService.list(new LambdaUpdateWrapper<>(BankOptionsEntity.class).in(BankOptionsEntity::getQuestionId, bankQuestionIds));
        Map<Integer, List<BankOptionsEntity>> optionsMap = options.stream().collect(Collectors.groupingBy(BankOptionsEntity::getQuestionId));
        // 处理当前页的数据
        List<BankQuestionsEntity> bankQuestions = new ArrayList<>();
        int successCount = 0;
        int failureCount = 0;

        for (BankQuestionsEntity bankQuestion : records) {
            try {
                QuestionPreviewReq requestParam = buildQuestionPreviewReq(bankQuestion,optionsMap);

                String htmlContent = richTextTemplateProcessor.processTemplate(textTemplate, requestParam);
                BankQuestionsEntity question = new BankQuestionsEntity();
                question.setId(bankQuestion.getId());

                // 根据类型更新相应字段
                if (2 == convertQuestionToHtmlReq.getType()) {
                    question.setQuestionHtml(htmlContent);
                } else if (3 == convertQuestionToHtmlReq.getType()) {
                    question.setHtml(htmlContent);
                }

                bankQuestions.add(question);
                successCount++;
            } catch (Exception e) {
                log.error("处理题库题目 ID={} 时出错", bankQuestion.getId(), e);
                failureCount++;
            }
        }

        if (CollectionUtil.isNotEmpty(bankQuestions)) {
            boolean updated = bankQuestionsService.updateBatchById(bankQuestions);
            log.info("成功更新{}条题库题目记录结果：{}", bankQuestions.size(), updated);
        }

        boolean hasMoreData = currentPage < bankQuestionsPage.getPages();
        return new ProcessResult(totalCount, successCount, failureCount, hasMoreData);
    }

    /**
     * 转换统计信息类
     */
    @Getter
    @Setter
    private static class ConversionStats {
        long totalCount = 0;
        int successCount = 0;
        int failureCount = 0;

        void update(ProcessResult result) {
            if (totalCount == 0) {
                totalCount = result.totalCount;
            }
            successCount += result.successCount;
            failureCount += result.failureCount;
        }
    }

    /**
     * 处理结果类
     */
    @Getter
    @Setter
    private static class ProcessResult {
        final long totalCount;
        final int successCount;
        final int failureCount;
        final boolean hasMoreData;

        ProcessResult(long totalCount, int successCount, int failureCount, boolean hasMoreData) {
            this.totalCount = totalCount;
            this.successCount = successCount;
            this.failureCount = failureCount;
            this.hasMoreData = hasMoreData;
        }
    }

    /**
     * 构建示例题目的预览请求参数
     * @param questionsResp 示例题目响应对象
     * @return 预览请求参数
     */
    private QuestionPreviewReq buildQuestionPreviewReq(ExampleQuestionsResp questionsResp) {
        QuestionPreviewReq requestParam = new QuestionPreviewReq();
        requestParam.setQuestion(questionsResp.getQuestion());
        requestParam.setAnswer(questionsResp.getAnswer());
        requestParam.setSolution(questionsResp.getSolution());
        requestParam.setType(questionsResp.getType());
        if (CollectionUtil.isNotEmpty(questionsResp.getOptions())) {
            requestParam.setOptions(questionsResp.getOptions().stream()
                    .map(QuestionOptionsResp::getContent)
                    .collect(Collectors.toList()));
        }
        return requestParam;
    }


    private QuestionPreviewReq buildQuestionPreviewReq(BankQuestionsEntity bankQuestion,Map<Integer, List<BankOptionsEntity>> optionsMap) {
        QuestionPreviewReq requestParam = new QuestionPreviewReq();
        requestParam.setQuestion(bankQuestion.getTitle());
        requestParam.setAnswer(bankQuestion.getAnswer());
        requestParam.setSolution(bankQuestion.getSolution());
        requestParam.setType(bankQuestion.getType());

        if(QuestionTypesEnums.isChoiceQuestion(bankQuestion.getType())){
            List<BankOptionsEntity> bankOptions = optionsMap.get(bankQuestion.getId());
            if(CollectionUtil.isNotEmpty(bankOptions)){
                requestParam.setOptions(bankOptions.stream()
                        .map(BankOptionsEntity::getContent)
                        .collect(Collectors.toList()));
            }
        }
        return requestParam;
    }
}