package com.seer.teach.admin.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seer.teach.admin.request.QuestionPreviewReq;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.teacher.module.entity.RichTextTemplateEntity;
import com.seer.teach.teacher.service.IRichTextTemplateService;
import freemarker.core.HTMLOutputFormat;
import freemarker.core.TemplateClassResolver;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;

/**
 * 富文本模板处理工具类
 */
@Slf4j
@Component
public class RichTextTemplateProcessor {

    private final IRichTextTemplateService richTextTemplateService;
    private final Configuration freemarkerConfig;

    public RichTextTemplateProcessor(IRichTextTemplateService richTextTemplateService, Configuration freemarkerConfig) {
        this.richTextTemplateService = richTextTemplateService;
        this.freemarkerConfig = freemarkerConfig;
        freemarkerConfig.setAPIBuiltinEnabled(true);
        freemarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
        freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
    }

    /**
     * 处理并渲染富文本模板
     *
     * @param requestParam 题目预览请求参数
     * @return 渲染后的HTML内容
     * @throws IOException IO异常
     * @throws TemplateException 模板异常
     */
    public String processTemplate(QuestionPreviewReq requestParam) throws IOException, TemplateException {
        // 获取模板
        RichTextTemplateEntity templateEntity = getTemplateByType(requestParam.getType());

        // 渲染模板
        return renderTemplate(templateEntity.getTemplateContent(), requestParam);
    }

    /**
     * 处理并渲染富文本模板
     *
     * @param templateEntity 模板实体
     * @param requestParam 题目预览请求参数
     * @return 渲染后的HTML内容
     * @throws IOException IO异常
     * @throws TemplateException 模板异常
     */
    public String processTemplate(RichTextTemplateEntity templateEntity,QuestionPreviewReq requestParam) throws IOException, TemplateException {
        // 渲染模板
        return renderTemplate(templateEntity.getTemplateContent(), requestParam);
    }

    /**
     * 处理并渲染富文本模板
     *
     * @param templateEntity 模板实体
     * @param dataModel 数据模型
     * @return 渲染后的HTML内容
     * @throws IOException IO异常
     * @throws TemplateException 模板异常
     */
    public String processTemplate(RichTextTemplateEntity templateEntity,Object dataModel) throws IOException, TemplateException {
        return renderTemplate(templateEntity.getTemplateContent(), dataModel);
    }


    /**
     * 根据题型获取模板
     *
     * @param templateType 模板类型
     * @return 模板实体
     */
    private RichTextTemplateEntity getTemplateByType(Integer templateType) {
        // 查询激活的模板并按优先级排序
        List<RichTextTemplateEntity> templateList = richTextTemplateService.list(
                new LambdaQueryWrapper<RichTextTemplateEntity>()
                        .eq(RichTextTemplateEntity::getIsActive, true)
                        .orderByDesc(RichTextTemplateEntity::getPriority)
        );

        AssertUtils.notEmpty(templateList, ResultCodeEnum.NOT_FOUND_TEMPLATE);

        // 先根据题型查找优先级最高的模板，如果找不到则查找通用模板
        return templateList.stream()
                .filter(template -> template.getTemplateType() == templateType)
                .findFirst()
                .orElseGet(() -> templateList.stream()
                        .filter(template -> template.getTemplateType() == 0)
                        .findFirst()
                        .orElse(templateList.get(0)));
    }

    /**
     * 渲染模板内容
     *
     * @param templateContent 模板内容
     * @param dataModel 数据模型
     * @return 渲染后的内容
     * @throws IOException IO异常
     * @throws TemplateException 模板异常
     */
    private String renderTemplate(String templateContent, Object dataModel) throws IOException, TemplateException {
        Template template = new Template("preview", new StringReader(templateContent), freemarkerConfig);
        StringWriter stringWriter = new StringWriter();
        template.process(dataModel, stringWriter);
        return stringWriter.toString();
    }
}
