# -*- coding: utf-8 -*-
"""佰奥莱博简报用图（Pillow 绘制，零外部依赖）：3 张 PNG"""
import json, os
from PIL import Image, ImageDraw, ImageFont

W = os.path.expanduser('~/Desktop/Hermes输出-工作类')
D = os.path.join(W, '数据')
OUT = os.path.join(W, '销售分析/佰奥莱博_三年简报_图')
os.makedirs(OUT, exist_ok=True)
data = json.load(open(os.path.join(D, '_bai_3y_data.json')))
Y = data['yearly']

BLUE = (21, 101, 192)
BLUE_D = (13, 71, 161)
BLUE_L = (144, 202, 249)
ORANGE = (242, 153, 74)
GRAY = (95, 107, 122)
LIGHT = (240, 244, 250)
WHITE = (255, 255, 255)

FONT_PATHS = ['/System/Library/Fonts/PingFang.ttc',
              '/System/Library/Fonts/Hiragino Sans GB.ttc',
              '/System/Library/Fonts/Supplemental/Songti.ttc']

def font(size):
    for p in FONT_PATHS:
        if os.path.exists(p):
            try:
                return ImageFont.truetype(p, size)
            except Exception:
                continue
    return ImageFont.load_default()

S = 2  # 2x 超采样

def canvas(w, h):
    im = Image.new('RGB', (w * S, h * S), WHITE)
    return im, ImageDraw.Draw(im)

def save(im, name, w, h):
    im = im.resize((w * S // 2, h * S // 2), Image.LANCZOS)
    p = os.path.join(OUT, name)
    im.save(p, quality=95)
    print('saved', p, im.size)

# ---------- 图1 年度销售额 ----------
def chart_year():
    w, h = 980, 460
    im, d = canvas(w, h)
    pad_l, pad_r, pad_t, pad_b = 110, 40, 70, 90
    plot_w, plot_h = w - pad_l - pad_r, h - pad_t - pad_b
    vals = [Y['2024']['amount'] / 1e4, Y['2025']['amount'] / 1e4, Y['2026']['amount'] / 1e4]
    labels = ['2024年', '2025年', '2026年1-9月']
    vmax = 120
    d.text((pad_l, 22 * S // 2), '近三年销售额（价税合计，万元）', font=font(30 * S // 2), fill=BLUE_D)
    # 网格
    for g in range(0, 5):
        v = vmax / 4 * g
        y = pad_t + plot_h - plot_h * (v / vmax)
        d.line([(pad_l, y), (pad_l + plot_w, y)], fill=LIGHT, width=2)
        d.text((pad_l - 78, y - 12), f'{v:.0f}', font=font(20 * S // 2), fill=GRAY)
    bw = 130
    gaps = (plot_w - bw * 3) / 3.4
    for i, (v, lb) in enumerate(zip(vals, labels)):
        x = pad_l + gaps * 0.6 + i * (bw + gaps)
        bh = plot_h * v / vmax
        y0 = pad_t + plot_h - bh
        color = BLUE if i < 2 else ORANGE
        d.rounded_rectangle([x, y0, x + bw, pad_t + plot_h], radius=10, fill=color)
        d.text((x + bw / 2 - 42, y0 - 38), f'{v:.2f}', font=font(26 * S // 2), fill=BLUE_D)
        d.text((x + bw / 2 - 52, pad_t + plot_h + 20), lb, font=font(22 * S // 2), fill=GRAY)
        if i == 1:
            d.text((x + bw / 2 - 46, y0 + 30), f'+{data["yearly"]["yoy_2025"]:.1f}%', font=font(22 * S // 2), fill=WHITE)
        if i == 2:
            d.text((x + bw / 2 - 46, y0 + 30), f'{data["yearly"]["yoy_2026"]:.1f}%', font=font(22 * S // 2), fill=WHITE)
    d.line([(pad_l, pad_t + plot_h), (pad_l + plot_w, pad_t + plot_h)], fill=(200, 210, 225), width=2)
    save(im, 'chart_year.png', w, h)

# ---------- 图2 月度走势 ----------
def chart_month():
    w, h = 980, 430
    im, d = canvas(w, h)
    pad_l, pad_r, pad_t, pad_b = 100, 40, 66, 86
    plot_w, plot_h = w - pad_l - pad_r, h - pad_t - pad_b
    m25 = [Y['2025']['monthly'].get(f'2025-{m:02d}', 0) / 1e4 for m in range(1, 13)]
    m26 = [Y['2026']['monthly'].get(f'2026-{m:02d}', 0) / 1e4 for m in range(1, 10)]
    vmax = 30
    d.text((pad_l, 20 * S // 2), '月度销售额对比（万元）：2025 全年 vs 2026 年 1-9 月', font=font(28 * S // 2), fill=BLUE_D)
    for g in range(5):
        v = vmax / 4 * g
        y = pad_t + plot_h - plot_h * v / vmax
        d.line([(pad_l, y), (pad_l + plot_w, y)], fill=LIGHT, width=2)
        d.text((pad_l - 62, y - 12), f'{v:.0f}', font=font(20 * S // 2), fill=GRAY)
    step = plot_w / 12.6
    def pts(series, off=0):
        return [(pad_l + step * (i + 0.7) + off, pad_t + plot_h - plot_h * (v / vmax)) for i, v in enumerate(series)]
    for i, m in enumerate(range(1, 13)):
        d.text((pad_l + step * (i + 0.7) - 12, pad_t + plot_h + 16), f'{m}月', font=font(18 * S // 2), fill=GRAY)
    p25 = pts(m25, -8)
    p26 = pts(m26, 8)
    d.line(p25, fill=BLUE_L, width=6, joint='curve')
    d.line(p26, fill=ORANGE, width=6, joint='curve')
    for x, y in p25:
        d.ellipse([x - 6, y - 6, x + 6, y + 6], fill=BLUE_L)
    for x, y in p26:
        d.ellipse([x - 8, y - 8, x + 8, y + 8], fill=ORANGE)
    # 图例
    lx, ly = pad_l + 10, pad_t + 6
    d.line([(lx, ly), (lx + 40, ly)], fill=BLUE_L, width=6)
    d.text((lx + 50, ly - 12), '2025年', font=font(20 * S // 2), fill=GRAY)
    d.line([(lx + 160, ly), (lx + 200, ly)], fill=ORANGE, width=6)
    d.text((lx + 210, ly - 12), '2026年', font=font(20 * S // 2), fill=GRAY)
    d.line([(pad_l, pad_t + plot_h), (pad_l + plot_w, pad_t + plot_h)], fill=(200, 210, 225), width=2)
    save(im, 'chart_month.png', w, h)

# ---------- 图3 FMD 直扩占比 ----------
def chart_mix():
    w, h = 980, 330
    im, d = canvas(w, h)
    pad_l = 100
    d.text((pad_l, 18 * S // 2), 'FMD 直扩系列占客户销售额比重（%）', font=font(28 * S // 2), fill=BLUE_D)
    shares = [Y['2024']['fmd_share'], Y['2025']['fmd_share'], Y['2026']['fmd_share']]
    labels = ['2024年', '2025年', '2026年1-9月']
    amounts = [Y['2024']['fmd_amount'] / 1e4, Y['2025']['fmd_amount'] / 1e4, Y['2026']['fmd_amount'] / 1e4]
    bar_h, gap = 46, 34
    top = 74
    full_w = w - pad_l - 200
    for i, (s, lb, a) in enumerate(zip(shares, labels, amounts)):
        y = top + i * (bar_h + gap)
        d.text((pad_l - 92, y + 8), lb, font=font(20 * S // 2), fill=GRAY)
        d.rounded_rectangle([pad_l, y, pad_l + full_w, y + bar_h], radius=8, fill=LIGHT)
        bl = full_w * s / 100
        d.rounded_rectangle([pad_l, y, pad_l + max(bl, 12), y + bar_h], radius=8, fill=BLUE if s > 50 else BLUE_L)
        d.text((pad_l + max(bl, 12) + 14, y + 8), f'{s:.1f}%  ({a:.2f}万)', font=font(21 * S // 2), fill=BLUE_D)
    save(im, 'chart_mix.png', w, h)

chart_year(); chart_month(); chart_mix()
