#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""公司综合实力与海外战略 · 单页 PPT 生成脚本

依赖：python-pptx >= 1.0
输出：/var/www/html/share/china-llm-overseas-strategy-pptx-20260805.pptx
"""

import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.oxml.ns import qn
from lxml import etree


# ============================================================
# 品牌色（与 share/build_pptx.py 同款）
# ============================================================
RED       = RGBColor(0xED, 0x1C, 0x24)
DARK      = RGBColor(0x1A, 0x1F, 0x2A)
GREY      = RGBColor(0x5A, 0x64, 0x78)
LGREY     = RGBColor(0x8A, 0x93, 0xA6)
LIGHT     = RGBColor(0xE7, 0xEA, 0xF0)
PANEL     = RGBColor(0xF7, 0xF8, 0xFA)
PANEL2    = RGBColor(0xEE, 0xF2, 0xF7)
WHITE     = RGBColor(0xFF, 0xFF, 0xFF)
ACCENT    = RGBColor(0xD4, 0x4A, 0x3A)
GREEN     = RGBColor(0x2E, 0xA8, 0x69)

# 中文字体（Linux 回退）
CN_FONT = "Noto Sans CJK SC"
EN_FONT = "Arial"

# 16:9
SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)

OUT_PPTX = "/var/www/html/share/china-llm-overseas-strategy-pptx-v2-20260805.pptx"


# ============================================================
# 基础绘制函数
# ============================================================
def add_rect(slide, x, y, w, h, fill, line=None, line_w=None):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid()
    shp.fill.fore_color.rgb = fill
    if line is None:
        shp.line.fill.background()
    else:
        shp.line.color.rgb = line
        if line_w is not None:
            shp.line.width = line_w
    shp.shadow.inherit = False
    return shp


def add_text(slide, x, y, w, h, text, *, size=14, bold=False, color=DARK,
             align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP, font=CN_FONT,
             fill=None, line_spacing=1.15):
    if fill is not None:
        add_rect(slide, x, y, w, h, fill)
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.margin_left = Inches(0.08)
    tf.margin_right = Inches(0.08)
    tf.margin_top = Inches(0.03)
    tf.margin_bottom = Inches(0.03)
    tf.word_wrap = True
    tf.vertical_anchor = anchor
    lines = text.split("\n") if isinstance(text, str) else [str(text)]
    for i, ln in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.alignment = align
        p.line_spacing = line_spacing
        run = p.add_run()
        run.text = ln
        run.font.size = Pt(size)
        run.font.bold = bold
        run.font.name = font
        # CJK 字体回退
        rPr = run._r.get_or_add_rPr()
        ea = rPr.find(qn('a:ea'))
        if ea is None:
            ea = etree.SubElement(rPr, qn('a:ea'))
        ea.set('typeface', CN_FONT)
        run.font.color.rgb = color
    return tb


def add_bullets(slide, x, y, w, h, items, *, size=12, color=DARK,
                bullet="•", bold_first_word=False, line_spacing=1.35):
    """带项目符号的多行文本，items 为字符串列表。"""
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.margin_left = Inches(0.08)
    tf.margin_right = Inches(0.08)
    tf.margin_top = Inches(0.04)
    tf.margin_bottom = Inches(0.04)
    tf.word_wrap = True
    for i, item in enumerate(items):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.alignment = PP_ALIGN.LEFT
        p.line_spacing = line_spacing
        p.space_after = Pt(2)
        # 主符号
        rb = p.add_run()
        rb.text = f"{bullet}  "
        rb.font.size = Pt(size)
        rb.font.name = CN_FONT
        rb.font.bold = True
        rb.font.color.rgb = RED
        rPr = rb._r.get_or_add_rPr()
        ea = rPr.find(qn('a:ea'))
        if ea is None:
            ea = etree.SubElement(rPr, qn('a:ea'))
        ea.set('typeface', CN_FONT)
        # 正文
        run = p.add_run()
        run.text = item
        run.font.size = Pt(size)
        run.font.name = CN_FONT
        run.font.color.rgb = color
        rPr2 = run._r.get_or_add_rPr()
        ea2 = rPr2.find(qn('a:ea'))
        if ea2 is None:
            ea2 = etree.SubElement(rPr2, qn('a:ea'))
        ea2.set('typeface', CN_FONT)
    return tb


# ============================================================
# 顶部 Title Bar
# ============================================================
def add_top_bar(slide, title, subtitle):
    add_rect(slide, 0, 0, SLIDE_W, Inches(0.95), DARK)
    # 左侧红色色块作为强调
    add_rect(slide, 0, 0, Inches(0.18), Inches(0.95), RED)
    add_text(slide, Inches(0.45), Inches(0.12), SLIDE_W - Inches(0.9), Inches(0.55),
             title, size=24, bold=True, color=WHITE, anchor=MSO_ANCHOR.MIDDLE)
    add_text(slide, Inches(0.45), Inches(0.58), SLIDE_W - Inches(0.9), Inches(0.34),
             subtitle, size=12, color=LIGHT, anchor=MSO_ANCHOR.TOP)


def add_footer(slide):
    # 底部深色收束条 + 一句话结论
    fh = Inches(0.65)
    add_rect(slide, 0, SLIDE_H - fh, SLIDE_W, fh, DARK)
    add_text(slide, Inches(0.5), SLIDE_H - fh + Inches(0.05),
             SLIDE_W - Inches(1), Inches(0.32),
             "ONE-LINE TAKEAWAY", size=10, bold=True, color=RED,
             anchor=MSO_ANCHOR.MIDDLE)
    add_text(slide, Inches(0.5), SLIDE_H - fh + Inches(0.28),
             SLIDE_W - Inches(1), Inches(0.32),
             "顶级资本背书 × 海外高速增长 × 轻资产高效率路径 —— "
             "公司正以最具资本效率的方式，做大海外模型业务的蛋糕。",
             size=14, bold=True, color=WHITE, anchor=MSO_ANCHOR.MIDDLE)
    # 右上角数据来源
    add_text(slide, SLIDE_W - Inches(4.5), Inches(0.30), Inches(4.0), Inches(0.4),
             "数据来源：公司公开披露｜受众多为投资人与管理层",
             size=9, color=LGREY, align=PP_ALIGN.RIGHT,
             anchor=MSO_ANCHOR.MIDDLE)


# ============================================================
# 三栏卡片
# ============================================================
def add_card(slide, x, y, w, h, *, head, big, unit, body_bullets,
             accent=RED, head_color=DARK):
    """单个板块卡片"""
    # 卡片背景
    add_rect(slide, x, y, w, h, WHITE, line=LIGHT, line_w=Pt(0.75))
    # 顶部色条
    add_rect(slide, x, y, w, Inches(0.08), accent)
    # 编号圆点
    cx = x + Inches(0.32)
    cy = y + Inches(0.30)
    circ = slide.shapes.add_shape(MSO_SHAPE.OVAL, cx, cy, Inches(0.42), Inches(0.42))
    circ.fill.solid()
    circ.fill.fore_color.rgb = accent
    circ.line.fill.background()
    circ.shadow.inherit = False
    add_text(slide, cx, cy, Inches(0.42), Inches(0.42), head.split("｜")[0],
             size=14, bold=True, color=WHITE,
             align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    # 板块名
    add_text(slide, x + Inches(0.85), y + Inches(0.26),
             w - Inches(1.0), Inches(0.5),
             head.split("｜", 1)[1] if "｜" in head else head,
             size=14, bold=True, color=head_color,
             anchor=MSO_ANCHOR.MIDDLE)
    # 大数字行
    big_y = y + Inches(0.95)
    add_text(slide, x + Inches(0.35), big_y, w - Inches(0.7), Inches(0.9),
             big, size=42, bold=True, color=accent,
             align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.MIDDLE)
    # 单位 / 解释
    add_text(slide, x + Inches(0.35), big_y + Inches(0.85),
             w - Inches(0.7), Inches(0.34),
             unit, size=11, bold=True, color=GREY)
    # 正文要点
    add_bullets(slide, x + Inches(0.35), big_y + Inches(1.25),
                w - Inches(0.7), h - Inches(1.25) - Inches(0.4),
                body_bullets, size=11, color=DARK, line_spacing=1.30)


# ============================================================
# 主流程
# ============================================================
prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H
BLANK = prs.slide_layouts[6]

s = prs.slides.add_slide(BLANK)

# 背景
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, PANEL)

# 标题条
add_top_bar(s,
            "公司综合实力与海外战略",
            "Capital-Grade Backdrop  ·  Fast-Growing Globalization  ·  Asset-Light Overseas Footprint")

# 三栏布局参数
TOP = Inches(1.20)
BOT_PAD = Inches(0.85)  # 给页脚留出
GUT = Inches(0.25)
CARD_Y = TOP
CARD_H = SLIDE_H - TOP - BOT_PAD
LEFT_M = Inches(0.35)
RIGHT_M = Inches(0.35)
TOTAL_W = SLIDE_W - LEFT_M - RIGHT_M
CARD_W = (TOTAL_W - 2 * GUT) // 3

# 板块一：综合实力
add_card(s, LEFT_M, CARD_Y, CARD_W, CARD_H,
         head="01｜综合实力",
         big="F轮 · 300亿",
         unit="2026.07.30 完成 F 轮融资｜估值 300 亿美元",
         body_bullets=[
             "团队规模 300+，产研与商业化组织持续扩张",
             "阿里巴巴、腾讯、红杉等战略 + 财务投资人多轮加注，构成强背书",
             "2026.07.30 完成 F 轮融资，估值达 300 亿美元",
             "正稳步筹备港股上市，打开国际资本通道、强化品牌公信力",
         ],
         accent=RED)

# 板块二：海外业务
x2 = LEFT_M + CARD_W + GUT
add_card(s, x2, CARD_Y, CARD_W, CARD_H,
         head="02｜海外业务",
         big="4× · 400%",
         unit="海外付费用户 4×  ·  API 收入 +400%（主要收入来源）",
         body_bullets=[
             "产品进入 200+ 个国家和地区，跨地域普适性已验证",
             "海外付费用户增长 4 倍，海外市场真实需求得到验证",
             "API 收入同比 +400%，已成为公司主要收入来源",
             "付费用户 × API 收入同步高增，进入「规模 × 单价」双轮驱动",
         ],
         accent=ACCENT)

# 板块三：海外基础设施战略
x3 = LEFT_M + 2 * (CARD_W + GUT)
add_card(s, x3, CARD_Y, CARD_W, CARD_H,
         head="03｜海外底座",
         big="租云 + 开源",
         unit="海外底座统一采用  「租云厂 + 开源权重托管」 路线",
         body_bullets=[
             "短期不自建海外 DC，不对外提供通用云服务",
             "不铺设海外交付 / 支持团队，聚焦产品化与 API 输出",
             "依托全球主流云厂 + 开源生态，快速触达 200+ 国家",
             "资本效率优先、路径自洽，已被增长数据验证",
         ],
         accent=GREEN)

# 底部小标签 + 数据来源
add_footer(s)

# 输出
os.makedirs(os.path.dirname(OUT_PPTX), exist_ok=True)
prs.save(OUT_PPTX)
print(f"OK  ->  {OUT_PPTX}")
print(f"URL ->  https://xybcloud.online/share/{os.path.basename(OUT_PPTX)}")
