package com.hotwj.platform.reportStatistics.service;

import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import org.dromara.common.core.utils.SpringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 报表打印任务构建器
 *
 * @author shihongwei
 */
public class ReportPrintJob {

    @Getter
    private final List<JobSegment> segments = new ArrayList<>();
    // 辅助函数：根据类型获取 Provider
    private final Function<String, IReportDataProvider> providerFinder;
    @Getter
    private Long companyId;
    @Getter
    private boolean useSeal = true;
    @Getter
    private boolean useWatermark = true;
    @Getter
    private String watermarkText;
    @Getter
    private boolean useFooterPageNumber = true;

    public ReportPrintJob(Function<String, IReportDataProvider> providerFinder) {
        this.providerFinder = providerFinder;
    }

    public ReportPrintJob() {
        this(null);
    }

    public ReportPrintJob withCompanyId(Long companyId) {
        this.companyId = companyId;
        return this;
    }

    /**
     * 是否使用公章 (默认 false)
     */
    public ReportPrintJob useSeal(boolean useSeal) {
        this.useSeal = useSeal;
        return this;
    }

    /**
     * 是否使用水印 (默认 true)
     */
    public ReportPrintJob useWatermark(boolean useWatermark) {
        this.useWatermark = useWatermark;
        return this;
    }

    /**
     * 设置自定义水印文字 (默认使用 appName)
     */
    public ReportPrintJob watermarkText(String text) {
        this.watermarkText = text;
        return this;
    }

    /**
     * 添加封面 (基于指定业务 Provider 的配置)
     *
     * @param targetProvider 业务 Provider，将使用其 getCoverProviderType() 和 getCoverData()
     * @param params         可选的覆盖参数
     */
    public ReportPrintJob addCover(IReportDataProvider targetProvider, Map<String, Object> params) {
        if (targetProvider == null) {
            return this;
        }

        String coverType = targetProvider.getCoverProviderType();
        // 自动获取封面数据
        Map<String, Object> coverData = targetProvider.getCoverData(params);
        return addCover(coverType, coverData);
    }

    /**
     * 添加指定类型的封面
     *
     * @param coverType 封面 Provider 类型
     * @param params    封面参数
     */
    public ReportPrintJob addCover(String coverType, Map<String, Object> params) {
        if (StrUtil.isBlank(coverType) || providerFinder == null) {
            return this;
        }

        IReportDataProvider coverProvider = providerFinder.apply(coverType);
        if (coverProvider != null) {
            add(coverProvider, params);
        }
        return this;
    }

    public ReportPrintJob useFooterPageNumber(boolean useFooterPageNumber) {
        this.useFooterPageNumber = useFooterPageNumber;
        return this;
    }

    /**
     * 添加封面 (使用默认配置)
     */
    public ReportPrintJob addCover(IReportDataProvider targetProvider) {
        return addCover(targetProvider, null);
    }

    /**
     * 添加单个报表段 (如封面)
     */
    public ReportPrintJob add(IReportDataProvider provider, Map<String, Object> params) {
        if (provider != null) {
            // 深拷贝 params 以防止外部修改，或者至少创建一个新 Map
            Map<String, Object> safeParams = params != null ? new HashMap<>(params) : new HashMap<>();
            segments.add(new JobSegment(provider, safeParams));
        }
        return this;
    }

    /**
     * 批量添加报表段 (如每个ID生成一份)
     */
    public ReportPrintJob addBatch(IReportDataProvider provider, List<String> ids, String idKey) {
        if (provider != null && ids != null) {
            // 防御性拷贝 ID 列表
            for (String id : ids) {
                Map<String, Object> params = new HashMap<>();
                params.put(idKey, id);
                segments.add(new JobSegment(provider, params));
            }
        }
        return this;
    }

    /**
     * 执行渲染
     */
    public byte[] render() {
        ReportRenderService service = SpringUtils.getBean(ReportRenderService.class);
        return service.renderJob(this);
    }

    @Getter
    public static class JobSegment {
        private final IReportDataProvider provider;
        private final Map<String, Object> params;

        public JobSegment(IReportDataProvider provider, Map<String, Object> params) {
            this.provider = provider;
            this.params = params;
        }

        public boolean isLandscape() {
            return provider.isLandscape();
        }
    }
}
