package shop.alien.store.util;

import lombok.extern.slf4j.Slf4j;
import shop.alien.entity.store.vo.StoreOperationalStatisticsComparisonVo;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 经营统计数据对比图片生成工具类
 * 将 StoreOperationalStatisticsComparisonVo 数据转换为图片
 *
 * @author system
 * @since 2026-01-05
 */
@Slf4j
public class StatisticsComparisonImageUtil {

    // 颜色定义
    private static final Color BACKGROUND_COLOR = Color.WHITE;
    private static final Color TEXT_COLOR = new Color(51, 51, 51); // #333333
    private static final Color HEADER_BG_COLOR = new Color(245, 245, 245); // #F5F5F5
    private static final Color POSITIVE_COLOR = new Color(76, 175, 80); // 绿色 #4CAF50
    private static final Color NEGATIVE_COLOR = new Color(244, 67, 54); // 红色 #F44336
    private static final Color SECTION_TITLE_COLOR = new Color(33, 33, 33); // #212121
    private static final Color BORDER_COLOR = new Color(224, 224, 224); // #E0E0E0

    // 字体：优先 classpath 内 fonts/ 下的字体文件（与 resources/fonts/ 对应），支持 .ttf / .otf
    private static final String[] FONT_RESOURCE_PATHS = {
            "fonts/NotoSansSC-Regular.ttf",
            "fonts/NotoSansCJKsc-Regular.otf",
            "/fonts/NotoSansSC-Regular.ttf",
            "/fonts/NotoSansCJKsc-Regular.otf"
    };
    private static final String[] FONT_FALLBACK_NAMES = {
            "Microsoft YaHei",
            "PingFang SC",
            "WenQuanYi Zen Hei",
            "WenQuanYi Micro Hei",
            "Noto Sans CJK SC",
            "Noto Sans SC",
            "SimSun",
            "STSong",
            "Source Han Sans SC",
            "DengXian"
    };
    private static volatile Font baseChineseFont;   // 从 TTF 加载的基准字体
    private static volatile String chineseFontName; // 系统字体名（当未加载 TTF 时）

    private static final int TITLE_FONT_SIZE = 24;
    private static final int SECTION_TITLE_FONT_SIZE = 18;
    private static final int DATA_FONT_SIZE = 14;
    private static final int LABEL_FONT_SIZE = 12;

    // 尺寸定义
    private static final int IMAGE_WIDTH = 800;
    private static final int PADDING = 20;
    private static final int SECTION_SPACING = 30;
    private static final int ROW_HEIGHT = 35;
    private static final int HEADER_HEIGHT = 50;

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00");
    private static final DecimalFormat PERCENT_FORMAT = new DecimalFormat("#,##0.00%");

    /** 从 classpath 读取字体资源为字节数组（JAR 内更可靠） */
    private static byte[] readFontBytes(String path) {
        ClassLoader cl = StatisticsComparisonImageUtil.class.getClassLoader();
        for (String p : new String[]{path, path.startsWith("/") ? path.substring(1) : "/" + path}) {
            InputStream is = cl.getResourceAsStream(p);
            if (is == null && Thread.currentThread().getContextClassLoader() != null) {
                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(p);
            }
            if (is == null) continue;
            try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
                byte[] buf = new byte[8192];
                int n;
                while ((n = is.read(buf)) != -1) out.write(buf, 0, n);
                return out.toByteArray();
            } catch (Exception ignored) {
            } finally {
                try { is.close(); } catch (Exception ignored) {}
            }
        }
        return null;
    }

    private static Font getChineseFont(int style, int size) {
        if (baseChineseFont != null) {
            return baseChineseFont.deriveFont(style, size);
        }
        if (chineseFontName != null) {
            return new Font(chineseFontName, style, size);
        }
        synchronized (StatisticsComparisonImageUtil.class) {
            if (baseChineseFont != null) return baseChineseFont.deriveFont(style, size);
            if (chineseFontName != null) return new Font(chineseFontName, style, size);
            for (String path : FONT_RESOURCE_PATHS) {
                byte[] bytes = readFontBytes(path);
                if (bytes == null || bytes.length == 0) continue;
                try {
                    baseChineseFont = Font.createFont(Font.TRUETYPE_FONT, new ByteArrayInputStream(bytes)).deriveFont(Font.PLAIN, 14f);
                    return baseChineseFont.deriveFont(style, size);
                } catch (Exception e1) {
                    try {
                        File tmp = File.createTempFile("noto_", path.endsWith(".otf") ? ".otf" : ".ttf");
                        Files.write(tmp.toPath(), bytes);
                        baseChineseFont = Font.createFont(Font.TRUETYPE_FONT, tmp).deriveFont(Font.PLAIN, 14f);
                        tmp.delete();
                        return baseChineseFont.deriveFont(style, size);
                    } catch (Exception e2) {
                        // skip
                    }
                }
            }
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            String[] names = ge.getAvailableFontFamilyNames();
            if (names != null) {
                for (String candidate : FONT_FALLBACK_NAMES) {
                    for (String name : names) {
                        if (!candidate.equals(name)) continue;
                        Font f = new Font(name, Font.PLAIN, 14);
                        if (f.canDisplayUpTo("经") >= 0) continue;
                        chineseFontName = name;
                        return new Font(chineseFontName, style, size);
                    }
                }
                for (String name : names) {
                    Font f = new Font(name, Font.PLAIN, 14);
                    if (f.canDisplayUpTo("经") >= 0) continue;
                    chineseFontName = name;
                    return new Font(chineseFontName, style, size);
                }
            }
            chineseFontName = Font.SANS_SERIF;
            return new Font(chineseFontName, style, size);
        }
    }

    /**
     * 将统计数据对比转换为图片字节数组
     *
     * @param comparison 统计数据对比对象
     * @return 图片字节数组
     */
    public static byte[] generateImage(StoreOperationalStatisticsComparisonVo comparison) {
        if (comparison == null) {
            throw new IllegalArgumentException("统计数据对比对象不能为空");
        }

        try {
            // 计算图片高度
            int totalHeight = calculateImageHeight(comparison);
            
            // 创建图片
            BufferedImage image = new BufferedImage(IMAGE_WIDTH, totalHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            
            // 设置抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            
            // 填充背景
            g2d.setColor(BACKGROUND_COLOR);
            g2d.fillRect(0, 0, IMAGE_WIDTH, totalHeight);
            
            int currentY = PADDING;
            
            // 绘制标题
            currentY = drawTitle(g2d, currentY, comparison);
            
            // 绘制日期范围
            currentY = drawDateRange(g2d, currentY, comparison);
            
            currentY += SECTION_SPACING;
            
            // 绘制流量数据
            if (comparison.getTrafficData() != null) {
                currentY = drawSection(g2d, currentY, "流量数据", 
                    buildTrafficDataRows(comparison.getTrafficData()));
            }
            
            // 绘制互动数据
            if (comparison.getInteractionData() != null) {
                currentY = drawSection(g2d, currentY, "互动数据", 
                    buildInteractionDataRows(comparison.getInteractionData()));
            }
            
            // 绘制优惠券数据
            if (comparison.getCouponData() != null) {
                currentY = drawSection(g2d, currentY, "优惠券", 
                    buildCouponDataRows(comparison.getCouponData()));
            }
            
            // 绘制代金券数据
            if (comparison.getVoucherData() != null) {
                currentY = drawSection(g2d, currentY, "代金券", 
                    buildVoucherDataRows(comparison.getVoucherData()));
            }
            
            // 绘制服务质量数据
            if (comparison.getServiceQualityData() != null) {
                currentY = drawSection(g2d, currentY, "服务质量", 
                    buildServiceQualityDataRows(comparison.getServiceQualityData()));
            }
            
            // 绘制价目表排名数据
            if (comparison.getPriceListRanking() != null && !comparison.getPriceListRanking().isEmpty()) {
                currentY = drawPriceListRankingSection(g2d, currentY, "价目表排名", 
                    comparison.getPriceListRanking());
            }
            
            g2d.dispose();
            
            // 转换为字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return baos.toByteArray();
            
        } catch (Exception e) {
            log.error("生成统计数据对比图片失败", e);
            throw new RuntimeException("生成图片失败: " + e.getMessage(), e);
        }
    }

    /**
     * 计算图片高度
     */
    private static int calculateImageHeight(StoreOperationalStatisticsComparisonVo comparison) {
        int height = PADDING * 2;
        height += HEADER_HEIGHT; // 标题
        height += 40; // 日期范围
        height += SECTION_SPACING;
        
        int rowCount = 0;
        if (comparison.getTrafficData() != null) {
            rowCount += 6; // 流量数据行数（6个字段）
        }
        if (comparison.getInteractionData() != null) {
            rowCount += 13; // 互动数据行数（13个字段）
        }
        if (comparison.getCouponData() != null) {
            rowCount += 10; // 优惠券数据行数（10个字段）
        }
        if (comparison.getVoucherData() != null) {
            rowCount += 10; // 代金券数据行数（10个字段）
        }
        if (comparison.getServiceQualityData() != null) {
            rowCount += 12; // 服务质量数据行数（12个字段）
        }
        if (comparison.getPriceListRanking() != null && !comparison.getPriceListRanking().isEmpty()) {
            // 价目表数据：每个价目表3个指标（浏览量、访客数、分享数）
            rowCount += comparison.getPriceListRanking().size() * 3;
        }
        
        height += rowCount * ROW_HEIGHT;
        height += (rowCount / 6 + 4) * SECTION_SPACING; // 区块间距
        
        return height;
    }

    /**
     * 绘制标题
     */
    private static int drawTitle(Graphics2D g2d, int y, StoreOperationalStatisticsComparisonVo comparison) {
        Font titleFont = getChineseFont(Font.BOLD, TITLE_FONT_SIZE);
        g2d.setFont(titleFont);
        g2d.setColor(SECTION_TITLE_COLOR);
        
        String title = "经营数据";
        FontMetrics fm = g2d.getFontMetrics();
        int titleWidth = fm.stringWidth(title);
        int titleX = (IMAGE_WIDTH - titleWidth) / 2;
        
        g2d.drawString(title, titleX, y + TITLE_FONT_SIZE);
        return y + HEADER_HEIGHT;
    }

    /**
     * 绘制日期范围
     */
    private static int drawDateRange(Graphics2D g2d, int y, StoreOperationalStatisticsComparisonVo comparison) {
        Font dateFont = getChineseFont(Font.PLAIN, DATA_FONT_SIZE);
        g2d.setFont(dateFont);
        g2d.setColor(TEXT_COLOR);
        
        String currentDate = formatDate(comparison.getCurrentStartTime()) + "-" + formatDate(comparison.getCurrentEndTime());
        String previousDate = formatDate(comparison.getPreviousStartTime()) + "-" + formatDate(comparison.getPreviousEndTime());
        
        int dateX = PADDING;
        g2d.drawString(currentDate, dateX, y);
        g2d.drawString(previousDate, dateX, y + 20);
        
        return y + 40;
    }

    /**
     * 格式化日期
     */
    private static String formatDate(String date) {
        if (date == null || date.length() < 10) {
            return date;
        }
        // 将 yyyy-MM-dd 转换为 yyyy/MM/dd
        return date.replace("-", "/");
    }

    /**
     * 绘制数据区块
     */
    private static int drawSection(Graphics2D g2d, int y, String sectionTitle, List<DataRow> rows) {
        if (rows == null || rows.isEmpty()) {
            return y;
        }
        
        // 绘制区块标题
        Font sectionFont = getChineseFont(Font.BOLD, SECTION_TITLE_FONT_SIZE);
        g2d.setFont(sectionFont);
        g2d.setColor(SECTION_TITLE_COLOR);
        g2d.drawString(sectionTitle, PADDING, y);
        y += 30;

        // 绘制表头
        y = drawTableHeader(g2d, y);

        // 绘制数据行
        Font dataFont = getChineseFont(Font.PLAIN, DATA_FONT_SIZE);
        Font labelFont = getChineseFont(Font.PLAIN, LABEL_FONT_SIZE);
        
        for (DataRow row : rows) {
            y = drawDataRow(g2d, y, row, dataFont, labelFont);
        }
        
        return y + SECTION_SPACING;
    }

    /**
     * 绘制表头
     */
    private static int drawTableHeader(Graphics2D g2d, int y) {
        // 绘制表头背景
        g2d.setColor(HEADER_BG_COLOR);
        g2d.fillRect(PADDING, y, IMAGE_WIDTH - PADDING * 2, ROW_HEIGHT);
        
        // 绘制表头文字
        Font headerFont = getChineseFont(Font.BOLD, LABEL_FONT_SIZE);
        g2d.setFont(headerFont);
        g2d.setColor(TEXT_COLOR);
        
        int col1X = PADDING + 10;
        int col2X = IMAGE_WIDTH / 2 - 80;
        int col3X = IMAGE_WIDTH / 2 + 20;
        int col4X = IMAGE_WIDTH - PADDING - 100;
        
        g2d.drawString("指标", col1X, y + 20);
        g2d.drawString("当期", col2X, y + 20);
        g2d.drawString("上期", col3X, y + 20);
        g2d.drawString("变化率", col4X, y + 20);
        
        // 绘制边框
        g2d.setColor(BORDER_COLOR);
        g2d.drawRect(PADDING, y, IMAGE_WIDTH - PADDING * 2, ROW_HEIGHT);
        
        return y + ROW_HEIGHT;
    }

    /**
     * 绘制数据行
     */
    private static int drawDataRow(Graphics2D g2d, int y, DataRow row, Font dataFont, Font labelFont) {
        // 绘制行背景（交替颜色）
        if ((y / ROW_HEIGHT) % 2 == 0) {
            g2d.setColor(new Color(250, 250, 250));
            g2d.fillRect(PADDING, y, IMAGE_WIDTH - PADDING * 2, ROW_HEIGHT);
        }
        
        // 绘制指标名称
        g2d.setFont(labelFont);
        g2d.setColor(TEXT_COLOR);
        g2d.drawString(row.getLabel(), PADDING + 10, y + 22);
        
        // 绘制当期值
        g2d.setFont(dataFont);
        String currentValue = formatValue(row.getCurrent());
        g2d.drawString(currentValue, IMAGE_WIDTH / 2 - 80, y + 22);
        
        // 绘制上期值
        String previousValue = formatValue(row.getPrevious());
        g2d.drawString(previousValue, IMAGE_WIDTH / 2 + 20, y + 22);
        
        // 绘制变化率（带颜色）
        String changeRate = formatChangeRate(row.getChangeRate());
        Color changeColor = row.getChangeRate() != null && row.getChangeRate().compareTo(BigDecimal.ZERO) >= 0 
            ? POSITIVE_COLOR : NEGATIVE_COLOR;
        g2d.setColor(changeColor);
        g2d.drawString(changeRate, IMAGE_WIDTH - PADDING - 100, y + 22);
        
        // 绘制边框
        g2d.setColor(BORDER_COLOR);
        g2d.drawLine(PADDING, y + ROW_HEIGHT, IMAGE_WIDTH - PADDING, y + ROW_HEIGHT);
        
        return y + ROW_HEIGHT;
    }

    /**
     * 格式化数值
     */
    private static String formatValue(Object value) {
        if (value == null) {
            return "0";
        }
        if (value instanceof BigDecimal) {
            BigDecimal bd = (BigDecimal) value;
            if (bd.scale() > 0) {
                return DECIMAL_FORMAT.format(bd);
            } else {
                return String.valueOf(bd.longValue());
            }
        }
        if (value instanceof Number) {
            return DECIMAL_FORMAT.format(((Number) value).doubleValue());
        }
        return String.valueOf(value);
    }

    /**
     * 格式化变化率
     */
    private static String formatChangeRate(BigDecimal changeRate) {
        if (changeRate == null) {
            return "0.00%";
        }
        String sign = changeRate.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
        return sign + PERCENT_FORMAT.format(changeRate.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 构建流量数据行（按照实体类字段顺序）
     */
    private static List<DataRow> buildTrafficDataRows(StoreOperationalStatisticsComparisonVo.TrafficDataComparison data) {
        List<DataRow> rows = new ArrayList<>();
        // 1. 店铺搜索量对比
        if (data.getStoreSearchVolume() != null) {
            rows.add(new DataRow("店铺搜索量对比", data.getStoreSearchVolume().getCurrent(),
                data.getStoreSearchVolume().getPrevious(), data.getStoreSearchVolume().getChangeRate()));
        }
        // 2. 浏览量对比
        if (data.getPageViews() != null) {
            rows.add(new DataRow("浏览量对比", data.getPageViews().getCurrent(),
                data.getPageViews().getPrevious(), data.getPageViews().getChangeRate()));
        }
        // 3. 访客数对比
        if (data.getVisitors() != null) {
            rows.add(new DataRow("访客数对比", data.getVisitors().getCurrent(),
                data.getVisitors().getPrevious(), data.getVisitors().getChangeRate()));
        }
        // 4. 新增访客数对比
        if (data.getNewVisitors() != null) {
            rows.add(new DataRow("新增访客数对比", data.getNewVisitors().getCurrent(),
                data.getNewVisitors().getPrevious(), data.getNewVisitors().getChangeRate()));
        }
        // 5. 访问时长对比
        if (data.getVisitDuration() != null) {
            rows.add(new DataRow("访问时长对比", data.getVisitDuration().getCurrent(),
                data.getVisitDuration().getPrevious(), data.getVisitDuration().getChangeRate()));
        }
        // 6. 平均访问时长对比
        if (data.getAvgVisitDuration() != null) {
            rows.add(new DataRow("平均访问时长对比", data.getAvgVisitDuration().getCurrent(),
                data.getAvgVisitDuration().getPrevious(), data.getAvgVisitDuration().getChangeRate()));
        }
        return rows;
    }

    /**
     * 构建互动数据行（按照实体类字段顺序）
     */
    private static List<DataRow> buildInteractionDataRows(StoreOperationalStatisticsComparisonVo.InteractionDataComparison data) {
        List<DataRow> rows = new ArrayList<>();
        // 1. 店铺收藏次数对比
        if (data.getStoreCollectionCount() != null) {
            rows.add(new DataRow("店铺收藏次数对比", data.getStoreCollectionCount().getCurrent(),
                data.getStoreCollectionCount().getPrevious(), data.getStoreCollectionCount().getChangeRate()));
        }
        // 2. 店铺分享次数对比
        if (data.getStoreShareCount() != null) {
            rows.add(new DataRow("店铺分享次数对比", data.getStoreShareCount().getCurrent(),
                data.getStoreShareCount().getPrevious(), data.getStoreShareCount().getChangeRate()));
        }
        // 3. 店铺打卡次数对比
        if (data.getStoreCheckInCount() != null) {
            rows.add(new DataRow("店铺打卡次数对比", data.getStoreCheckInCount().getCurrent(),
                data.getStoreCheckInCount().getPrevious(), data.getStoreCheckInCount().getChangeRate()));
        }
        // 4. 咨询商家次数对比
        if (data.getConsultMerchantCount() != null) {
            rows.add(new DataRow("咨询商家次数对比", data.getConsultMerchantCount().getCurrent(),
                data.getConsultMerchantCount().getPrevious(), data.getConsultMerchantCount().getChangeRate()));
        }
        // 5. 好友数量对比
        if (data.getFriendsCount() != null) {
            rows.add(new DataRow("好友数量对比", data.getFriendsCount().getCurrent(),
                data.getFriendsCount().getPrevious(), data.getFriendsCount().getChangeRate()));
        }
        // 6. 关注数量对比
        if (data.getFollowCount() != null) {
            rows.add(new DataRow("关注数量对比", data.getFollowCount().getCurrent(),
                data.getFollowCount().getPrevious(), data.getFollowCount().getChangeRate()));
        }
        // 7. 粉丝数量对比
        if (data.getFansCount() != null) {
            rows.add(new DataRow("粉丝数量对比", data.getFansCount().getCurrent(),
                data.getFansCount().getPrevious(), data.getFansCount().getChangeRate()));
        }
        // 8. 发布动态数量对比
        if (data.getPostsPublishedCount() != null) {
            rows.add(new DataRow("发布动态数量对比", data.getPostsPublishedCount().getCurrent(),
                data.getPostsPublishedCount().getPrevious(), data.getPostsPublishedCount().getChangeRate()));
        }
        // 9. 动态点赞数量对比
        if (data.getPostLikesCount() != null) {
            rows.add(new DataRow("动态点赞数量对比", data.getPostLikesCount().getCurrent(),
                data.getPostLikesCount().getPrevious(), data.getPostLikesCount().getChangeRate()));
        }
        // 10. 动态评论数量对比
        if (data.getPostCommentsCount() != null) {
            rows.add(new DataRow("动态评论数量对比", data.getPostCommentsCount().getCurrent(),
                data.getPostCommentsCount().getPrevious(), data.getPostCommentsCount().getChangeRate()));
        }
        // 11. 动态转发数量对比
        if (data.getPostSharesCount() != null) {
            rows.add(new DataRow("动态转发数量对比", data.getPostSharesCount().getCurrent(),
                data.getPostSharesCount().getPrevious(), data.getPostSharesCount().getChangeRate()));
        }
        // 12. 被举报次数对比
        if (data.getReportedCount() != null) {
            rows.add(new DataRow("被举报次数对比", data.getReportedCount().getCurrent(),
                data.getReportedCount().getPrevious(), data.getReportedCount().getChangeRate()));
        }
        // 13. 被拉黑次数对比
        if (data.getBlockedCount() != null) {
            rows.add(new DataRow("被拉黑次数对比", data.getBlockedCount().getCurrent(),
                data.getBlockedCount().getPrevious(), data.getBlockedCount().getChangeRate()));
        }
        return rows;
    }

    /**
     * 构建优惠券数据行（按照实体类字段顺序）
     */
    private static List<DataRow> buildCouponDataRows(StoreOperationalStatisticsComparisonVo.CouponDataComparison data) {
        List<DataRow> rows = new ArrayList<>();
        // 1. 赠送好友数量对比
        if (data.getGiftToFriendsCount() != null) {
            rows.add(new DataRow("赠送好友数量对比", data.getGiftToFriendsCount().getCurrent(), 
                data.getGiftToFriendsCount().getPrevious(), data.getGiftToFriendsCount().getChangeRate()));
        }
        // 2. 赠送好友金额合计对比
        if (data.getGiftToFriendsAmount() != null) {
            rows.add(new DataRow("赠送好友金额合计对比", data.getGiftToFriendsAmount().getCurrent(), 
                data.getGiftToFriendsAmount().getPrevious(), data.getGiftToFriendsAmount().getChangeRate()));
        }
        // 3. 赠送好友使用数量对比
        if (data.getGiftToFriendsUsedCount() != null) {
            rows.add(new DataRow("赠送好友使用数量对比", data.getGiftToFriendsUsedCount().getCurrent(), 
                data.getGiftToFriendsUsedCount().getPrevious(), data.getGiftToFriendsUsedCount().getChangeRate()));
        }
        // 4. 赠送好友使用金额合计对比
        if (data.getGiftToFriendsUsedAmount() != null) {
            rows.add(new DataRow("赠送好友使用金额合计对比", data.getGiftToFriendsUsedAmount().getCurrent(), 
                data.getGiftToFriendsUsedAmount().getPrevious(), data.getGiftToFriendsUsedAmount().getChangeRate()));
        }
        // 5. 赠送好友使用金额占比对比
        if (data.getGiftToFriendsUsedAmountRatio() != null) {
            rows.add(new DataRow("赠送好友使用金额占比对比", data.getGiftToFriendsUsedAmountRatio().getCurrent(), 
                data.getGiftToFriendsUsedAmountRatio().getPrevious(), data.getGiftToFriendsUsedAmountRatio().getChangeRate()));
        }
        // 6. 好友赠送数量对比
        if (data.getFriendsGiftCount() != null) {
            rows.add(new DataRow("好友赠送数量对比", data.getFriendsGiftCount().getCurrent(), 
                data.getFriendsGiftCount().getPrevious(), data.getFriendsGiftCount().getChangeRate()));
        }
        // 7. 好友赠送金额合计对比
        if (data.getFriendsGiftAmount() != null) {
            rows.add(new DataRow("好友赠送金额合计对比", data.getFriendsGiftAmount().getCurrent(), 
                data.getFriendsGiftAmount().getPrevious(), data.getFriendsGiftAmount().getChangeRate()));
        }
        // 8. 好友赠送使用数量对比
        if (data.getFriendsGiftUsedCount() != null) {
            rows.add(new DataRow("好友赠送使用数量对比", data.getFriendsGiftUsedCount().getCurrent(), 
                data.getFriendsGiftUsedCount().getPrevious(), data.getFriendsGiftUsedCount().getChangeRate()));
        }
        // 9. 好友赠送使用金额合计对比
        if (data.getFriendsGiftUsedAmount() != null) {
            rows.add(new DataRow("好友赠送使用金额合计对比", data.getFriendsGiftUsedAmount().getCurrent(), 
                data.getFriendsGiftUsedAmount().getPrevious(), data.getFriendsGiftUsedAmount().getChangeRate()));
        }
        // 10. 好友赠送使用金额占比对比
        if (data.getFriendsGiftUsedAmountRatio() != null) {
            rows.add(new DataRow("好友赠送使用金额占比对比", data.getFriendsGiftUsedAmountRatio().getCurrent(), 
                data.getFriendsGiftUsedAmountRatio().getPrevious(), data.getFriendsGiftUsedAmountRatio().getChangeRate()));
        }
        return rows;
    }

    /**
     * 构建代金券数据行（按照实体类字段顺序）
     */
    private static List<DataRow> buildVoucherDataRows(StoreOperationalStatisticsComparisonVo.VoucherDataComparison data) {
        List<DataRow> rows = new ArrayList<>();
        // 1. 赠送好友数量对比
        if (data.getGiftToFriendsCount() != null) {
            rows.add(new DataRow("赠送好友数量对比", data.getGiftToFriendsCount().getCurrent(), 
                data.getGiftToFriendsCount().getPrevious(), data.getGiftToFriendsCount().getChangeRate()));
        }
        // 2. 赠送好友金额合计对比
        if (data.getGiftToFriendsAmount() != null) {
            rows.add(new DataRow("赠送好友金额合计对比", data.getGiftToFriendsAmount().getCurrent(), 
                data.getGiftToFriendsAmount().getPrevious(), data.getGiftToFriendsAmount().getChangeRate()));
        }
        // 3. 赠送好友使用数量对比
        if (data.getGiftToFriendsUsedCount() != null) {
            rows.add(new DataRow("赠送好友使用数量对比", data.getGiftToFriendsUsedCount().getCurrent(), 
                data.getGiftToFriendsUsedCount().getPrevious(), data.getGiftToFriendsUsedCount().getChangeRate()));
        }
        // 4. 赠送好友使用金额合计对比
        if (data.getGiftToFriendsUsedAmount() != null) {
            rows.add(new DataRow("赠送好友使用金额合计对比", data.getGiftToFriendsUsedAmount().getCurrent(), 
                data.getGiftToFriendsUsedAmount().getPrevious(), data.getGiftToFriendsUsedAmount().getChangeRate()));
        }
        // 5. 赠送好友使用金额占比对比
        if (data.getGiftToFriendsUsedAmountRatio() != null) {
            rows.add(new DataRow("赠送好友使用金额占比对比", data.getGiftToFriendsUsedAmountRatio().getCurrent(), 
                data.getGiftToFriendsUsedAmountRatio().getPrevious(), data.getGiftToFriendsUsedAmountRatio().getChangeRate()));
        }
        // 6. 好友赠送数量对比
        if (data.getFriendsGiftCount() != null) {
            rows.add(new DataRow("好友赠送数量对比", data.getFriendsGiftCount().getCurrent(), 
                data.getFriendsGiftCount().getPrevious(), data.getFriendsGiftCount().getChangeRate()));
        }
        // 7. 好友赠送金额合计对比
        if (data.getFriendsGiftAmount() != null) {
            rows.add(new DataRow("好友赠送金额合计对比", data.getFriendsGiftAmount().getCurrent(), 
                data.getFriendsGiftAmount().getPrevious(), data.getFriendsGiftAmount().getChangeRate()));
        }
        // 8. 好友赠送使用数量对比
        if (data.getFriendsGiftUsedCount() != null) {
            rows.add(new DataRow("好友赠送使用数量对比", data.getFriendsGiftUsedCount().getCurrent(), 
                data.getFriendsGiftUsedCount().getPrevious(), data.getFriendsGiftUsedCount().getChangeRate()));
        }
        // 9. 好友赠送使用金额合计对比
        if (data.getFriendsGiftUsedAmount() != null) {
            rows.add(new DataRow("好友赠送使用金额合计对比", data.getFriendsGiftUsedAmount().getCurrent(), 
                data.getFriendsGiftUsedAmount().getPrevious(), data.getFriendsGiftUsedAmount().getChangeRate()));
        }
        // 10. 好友赠送使用金额占比对比
        if (data.getFriendsGiftUsedAmountRatio() != null) {
            rows.add(new DataRow("好友赠送使用金额占比对比", data.getFriendsGiftUsedAmountRatio().getCurrent(), 
                data.getFriendsGiftUsedAmountRatio().getPrevious(), data.getFriendsGiftUsedAmountRatio().getChangeRate()));
        }
        return rows;
    }

    /**
     * 构建服务质量数据行（按照实体类字段顺序）
     */
    private static List<DataRow> buildServiceQualityDataRows(StoreOperationalStatisticsComparisonVo.ServiceQualityDataComparison data) {
        List<DataRow> rows = new ArrayList<>();
        // 1. 店铺评分对比
        if (data.getStoreRating() != null) {
            rows.add(new DataRow("店铺评分对比", data.getStoreRating().getCurrent(), 
                data.getStoreRating().getPrevious(), data.getStoreRating().getChangeRate()));
        }
        // 2. 评分1对比
        if (data.getScoreOne() != null) {
            rows.add(new DataRow("评分1对比", data.getScoreOne().getCurrent(), 
                data.getScoreOne().getPrevious(), data.getScoreOne().getChangeRate()));
        }
        // 3. 评分2对比
        if (data.getScoreTwo() != null) {
            rows.add(new DataRow("评分2对比", data.getScoreTwo().getCurrent(), 
                data.getScoreTwo().getPrevious(), data.getScoreTwo().getChangeRate()));
        }
        // 4. 评分3对比
        if (data.getScoreThree() != null) {
            rows.add(new DataRow("评分3对比", data.getScoreThree().getCurrent(), 
                data.getScoreThree().getPrevious(), data.getScoreThree().getChangeRate()));
        }
        // 5. 评价数量对比
        if (data.getTotalReviews() != null) {
            rows.add(new DataRow("评价数量对比", data.getTotalReviews().getCurrent(), 
                data.getTotalReviews().getPrevious(), data.getTotalReviews().getChangeRate()));
        }
        // 6. 好评数量对比
        if (data.getPositiveReviews() != null) {
            rows.add(new DataRow("好评数量对比", data.getPositiveReviews().getCurrent(), 
                data.getPositiveReviews().getPrevious(), data.getPositiveReviews().getChangeRate()));
        }
        // 7. 中评数量对比
        if (data.getNeutralReviews() != null) {
            rows.add(new DataRow("中评数量对比", data.getNeutralReviews().getCurrent(), 
                data.getNeutralReviews().getPrevious(), data.getNeutralReviews().getChangeRate()));
        }
        // 8. 差评数量对比
        if (data.getNegativeReviews() != null) {
            rows.add(new DataRow("差评数量对比", data.getNegativeReviews().getCurrent(), 
                data.getNegativeReviews().getPrevious(), data.getNegativeReviews().getChangeRate()));
        }
        // 9. 差评占比对比
        if (data.getNegativeReviewRatio() != null) {
            rows.add(new DataRow("差评占比对比", data.getNegativeReviewRatio().getCurrent(), 
                data.getNegativeReviewRatio().getPrevious(), data.getNegativeReviewRatio().getChangeRate()));
        }
        // 10. 差评申诉次数对比
        if (data.getNegativeReviewAppealsCount() != null) {
            rows.add(new DataRow("差评申诉次数对比", data.getNegativeReviewAppealsCount().getCurrent(), 
                data.getNegativeReviewAppealsCount().getPrevious(), data.getNegativeReviewAppealsCount().getChangeRate()));
        }
        // 11. 差评申诉成功次数对比
        if (data.getNegativeReviewAppealsSuccessCount() != null) {
            rows.add(new DataRow("差评申诉成功次数对比", data.getNegativeReviewAppealsSuccessCount().getCurrent(), 
                data.getNegativeReviewAppealsSuccessCount().getPrevious(), data.getNegativeReviewAppealsSuccessCount().getChangeRate()));
        }
        // 12. 差评申诉成功占比对比
        if (data.getNegativeReviewAppealsSuccessRatio() != null) {
            rows.add(new DataRow("差评申诉成功占比对比", data.getNegativeReviewAppealsSuccessRatio().getCurrent(), 
                data.getNegativeReviewAppealsSuccessRatio().getPrevious(), data.getNegativeReviewAppealsSuccessRatio().getChangeRate()));
        }
        return rows;
    }

    /**
     * 绘制价目表排名数据区块（特殊格式，每个价目表显示3个指标）
     */
    private static int drawPriceListRankingSection(Graphics2D g2d, int y, String sectionTitle, 
                                                   List<StoreOperationalStatisticsComparisonVo.PriceListRankingComparison> rankings) {
        if (rankings == null || rankings.isEmpty()) {
            return y;
        }
        
        // 绘制区块标题
        Font sectionFont = getChineseFont(Font.BOLD, SECTION_TITLE_FONT_SIZE);
        g2d.setFont(sectionFont);
        g2d.setColor(SECTION_TITLE_COLOR);
        g2d.drawString(sectionTitle, PADDING, y);
        y += 30;

        Font dataFont = getChineseFont(Font.PLAIN, DATA_FONT_SIZE);
        Font labelFont = getChineseFont(Font.PLAIN, LABEL_FONT_SIZE);

        // 遍历每个价目表
        for (StoreOperationalStatisticsComparisonVo.PriceListRankingComparison ranking : rankings) {
            // 绘制价目表名称（作为子标题）
            g2d.setFont(getChineseFont(Font.BOLD, LABEL_FONT_SIZE));
            g2d.setColor(new Color(66, 66, 66));
            String priceListName = ranking.getPriceListItemName() != null ? ranking.getPriceListItemName() : 
                ("价目表ID: " + ranking.getPriceId());
            g2d.drawString(priceListName, PADDING + 20, y);
            y += 25;
            
            // 绘制表头
            y = drawTableHeader(g2d, y);
            
            // 绘制该价目表的3个指标
            List<DataRow> rows = new ArrayList<>();
            if (ranking.getPageViews() != null) {
                rows.add(new DataRow("浏览量", ranking.getPageViews().getCurrent(), 
                    ranking.getPageViews().getPrevious(), ranking.getPageViews().getChangeRate()));
            }
            if (ranking.getVisitors() != null) {
                rows.add(new DataRow("访客", ranking.getVisitors().getCurrent(), 
                    ranking.getVisitors().getPrevious(), ranking.getVisitors().getChangeRate()));
            }
            if (ranking.getShares() != null) {
                rows.add(new DataRow("分享数", ranking.getShares().getCurrent(), 
                    ranking.getShares().getPrevious(), ranking.getShares().getChangeRate()));
            }
            
            // 绘制数据行
            for (DataRow row : rows) {
                y = drawDataRow(g2d, y, row, dataFont, labelFont);
            }
            
            y += SECTION_SPACING / 2; // 价目表之间的间距
        }
        
        return y + SECTION_SPACING;
    }

    /**
     * 数据行内部类
     */
    private static class DataRow {
        private String label;
        private Object current;
        private Object previous;
        private BigDecimal changeRate;

        public DataRow(String label, Object current, Object previous, BigDecimal changeRate) {
            this.label = label;
            this.current = current;
            this.previous = previous;
            this.changeRate = changeRate;
        }

        public String getLabel() {
            return label;
        }

        public Object getCurrent() {
            return current;
        }

        public Object getPrevious() {
            return previous;
        }

        public BigDecimal getChangeRate() {
            return changeRate;
        }
    }
}
