package com.zt.plat.module.base.service.doctemplate.render;

import com.zt.plat.framework.common.exception.ServiceException;
import com.zt.plat.module.base.controller.admin.doctemplate.vo.DocTemplateInstanceRespVO;
import com.zt.plat.module.base.dal.dataobject.doctemplate.DocTemplateTagDO;
import com.zt.plat.module.base.dal.dao.doctemplate.DocTemplateTagMapper;
import com.zt.plat.module.base.service.doctemplate.DocTemplateInstanceService;
import com.zt.plat.module.base.service.doctemplate.render.export.DocTemplateExportStrategyFactory;
import com.zt.plat.module.base.service.doctemplate.render.export.IExportStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 增强版模板实例渲染服务（核心服务）
 * 基于现有 DocTemplateRenderService 扩展，支持多数据源和策略模式
 *
 * @author hwc
 */
@Service
@Slf4j
public class DocTemplateAdvancedRenderService {


    @Resource
    private DocTemplateInstanceService docTemplateInstanceService;

    @Resource
    private DocTemplateTagMapper docTemplateTagMapper;

    @Resource
    private IVelocityRenderEngine velocityRenderEngine;

    @Resource
    private DocTemplateDataSourceProviderFactory dataSourceProviderFactory;

    @Resource
    private DocTemplateExportStrategyFactory exportStrategyFactory;

    /**
     * 渲染模板实例并导出
     */
    public Object renderAndExport(TemplateRenderRequest request) {
        log.info("开始渲染和导出，模板实例ID: {}, 导出类型: {}",
                request.getTemplateInstanceId(), request.getExportType());

        // 1. 加载模板实例
        DocTemplateInstanceRespVO instance = docTemplateInstanceService
                .getTemplateInstance(request.getTemplateInstanceId());

        if (instance == null) {
            throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR.value(),"模板实例不存在: " + request.getTemplateInstanceId());
        }

        // 2. 加载标签定义（用于获取标签的默认值）
        List<DocTemplateTagDO> tags = getTemplateTags(instance);

        if (tags == null || tags.isEmpty()) {
            log.warn("模板实例 {} 没有关联的标签定义", request.getTemplateInstanceId());
        }

        Map<String, DocTemplateTagDO> tagMap = tags.stream()
                .collect(Collectors.toMap(DocTemplateTagDO::getTagCode, t -> t));

        // 3. 收集所有需要填充的字段值
        Map<String, Object> fillData = new HashMap<>();
        for (DocTemplateTagDO tag : tags) {
            Object value = getFieldValue(tag, request, instance.getInstanceName());
            fillData.put(tag.getTagCode(), value != null ? value : "");
        }

        // 4. Velocity 渲染
        String templateContent = instance.getEditedContent();
        if (templateContent == null || templateContent.trim().isEmpty()) {
            throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "模板实例内容为空");
        }

        String htmlContent = velocityRenderEngine.render(templateContent, fillData);

        // 5. 获取导出策略并执行导出
        IExportStrategy exportStrategy = exportStrategyFactory
                .createStrategy(request.getExportType());

        Object result = exportStrategy.export(htmlContent, instance.getInstanceName());

        log.info("渲染和导出完成，模板实例ID: {}", request.getTemplateInstanceId());
        return result;
    }

    /**
     * 获取单个字段的值
     * 优先级：调用方覆盖 > 默认值
     */
    private Object getFieldValue(DocTemplateTagDO tag, TemplateRenderRequest request,
                                 String templateName) {
        String fieldName = tag.getTagCode();

        // 判断是否有字段级的数据源覆盖
        DocTemplateDataSourceType sourceType = null;
        if (request.getFieldDataSources() != null) {
            sourceType = request.getFieldDataSources().get(fieldName);
        }

        // 如果有覆盖，从指定的数据源获取值
        if (sourceType != null) {
            try {
                IDataSourceProvider provider = dataSourceProviderFactory
                        .createProvider(
                                sourceType,
                                request.getDataSourceContext(),
                                templateName,
                                request.getBusinessType() != null ?
                                        request.getBusinessType() : templateName
                        );

                Map<String, Object> data = provider.getData(
                        request.getDataSourceContext(),
                        java.util.List.of(fieldName)
                );

                if (data.containsKey(fieldName)) {
                    Object value = data.get(fieldName);
                    if (value != null) {
                        log.debug("从数据源 {} 获取字段值: {} = {}", sourceType, fieldName, value);
                        return value;
                    }
                }
            } catch (Exception e) {
                log.warn("从数据源获取字段值失败，使用默认值: {}, 数据源: {}", fieldName, sourceType, e);
            }
        }

        // 使用默认值（从标签的defaultValue字段获取）
        String defaultValue = extractDefaultValue(tag);
        log.debug("使用标签默认值: {} = {}", fieldName, defaultValue);
        return defaultValue;
    }

    /**
     * 从标签定义中提取默认值
     */
    private String extractDefaultValue(DocTemplateTagDO tag) {
        if (tag.getDefaultValue() != null && !tag.getDefaultValue().trim().isEmpty()) {
            return tag.getDefaultValue();
        }
        return "";
    }

    /**
     * 获取模板实例关联的标签列表
     * 通过实例的 categoryId 查询该分类下的所有标签定义
     */
    private List<DocTemplateTagDO> getTemplateTags(DocTemplateInstanceRespVO instance) {
        if (instance.getCategoryId() == null) {
            log.warn("模板实例 {} 没有关联分类ID", instance.getId());
            return List.of();
        }

        try {
            // 通过 categoryId 查询该分类下的所有标签
            List<DocTemplateTagDO> tags = docTemplateTagMapper.selectList(
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<DocTemplateTagDO>()
                            .eq(DocTemplateTagDO::getCategoryId, instance.getCategoryId())
                            .eq(DocTemplateTagDO::getEnabled, "1")  // 只查询启用的标签
                            .orderByAsc(DocTemplateTagDO::getSort)
            );

            if (tags == null || tags.isEmpty()) {
                log.warn("分类ID {} 下没有找到标签定义", instance.getCategoryId());
                return List.of();
            }

            log.debug("从分类ID {} 获取到 {} 个标签定义", instance.getCategoryId(), tags.size());
            return tags;
        } catch (Exception e) {
            log.error("查询分类 {} 的标签列表失败", instance.getCategoryId(), e);
            return List.of();
        }
    }
}
