#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""在v7中插入赵云浩、刘子研2026丢失/新增商机各一页。"""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.oxml.ns import qn
from lxml import etree

ROOT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
SRC = os.path.join(ROOT, '经营分析/月报/2026年10月销售部工作汇报_草稿_20261108_v7.pptx')
LOGO = '/Users/liuxinyuan/work/公司资料/logo_transparent.png'

NAVY = RGBColor(0x0B, 0x2A, 0x4A)
BLUE = RGBColor(0x1F, 0x6F, 0xEB)
LIGHT = RGBColor(0xEA, 0xF2, 0xFB)
PALE = RGBColor(0xF5, 0xF8, 0xFC)
GREY = RGBColor(0x5B, 0x6B, 0x7F)
MIDGREY = RGBColor(0x8A, 0x99, 0xAA)
RED = RGBColor(0xC0, 0x39, 0x2B)
GREEN = RGBColor(0x1E, 0x84, 0x49)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)


def set_run(run, size=8, color=NAVY, bold=False):
    run.font.size = Pt(size); run.font.bold = bold
    run.font.color.rgb = color; run.font.name = 'Times New Roman'
    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', '宋体')
    cs = rPr.find(qn('a:cs'))
    if cs is None: cs = etree.SubElement(rPr, qn('a:cs'))
    cs.set('typeface', '宋体')


def add_text(slide, x, y, w, h, text, size=9, color=NAVY, bold=False,
             align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP, line_spacing=1.06):
    box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
    tf = box.text_frame
    tf.word_wrap = True
    tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
    tf.vertical_anchor = anchor
    for i, line in enumerate(str(text).split('\n')):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.alignment = align; p.line_spacing = line_spacing
        r = p.add_run(); r.text = line; set_run(r, size, color, bold)


def add_rect(slide, x, y, w, h, fill, line=None, radius=False):
    shp = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE if radius else MSO_SHAPE.RECTANGLE,
                                 Inches(x), Inches(y), Inches(w), Inches(h))
    shp.fill.solid(); shp.fill.fore_color.rgb = fill
    if line:
        shp.line.color.rgb = line; shp.line.width = Pt(0.75)
    else:
        shp.line.fill.background()
    if radius:
        try: shp.adjustments[0] = 0.08
        except Exception: pass


def add_header(s, name):
    add_rect(s, 0, 0, 13.333, 0.06, BLUE)
    if os.path.exists(LOGO):
        s.shapes.add_picture(LOGO, Inches(0.48), Inches(0.22), height=Inches(0.34))
    add_text(s, 0.48, 0.58, 12.0, 0.42, f'{name}｜2026 商机变化：丢失与新增', size=18, color=NAVY, bold=True)
    add_text(s, 0.48, 1.02, 12.3, 0.28,
             '2026年1-10月｜丢失=集团销售额 <2025全年50%｜新增=2025无销售、2026有销售｜单位：万元',
             size=8.6, color=GREY)


def add_cards(s, lost_label, lost_val, new_label, new_val):
    items = [('丢失集团', lost_label, RED), ('丢失额（2025→2026）', lost_val, NAVY),
             (new_label, new_val[0], GREEN), ('新增销售', new_val[1], BLUE)]
    for (label, value, color), x in zip(items, [0.48, 3.55, 6.62, 9.69]):
        add_rect(s, x, 1.40, 2.78, 0.66, PALE, line=RGBColor(0xDD, 0xE7, 0xF2), radius=True)
        add_text(s, x + 0.18, 1.47, 2.45, 0.17, label, size=7.4, color=GREY)
        add_text(s, x + 0.18, 1.65, 2.45, 0.28, value, size=13.2, color=color, bold=True)


def add_panel_title(s, x, y, w, text, color=NAVY):
    add_rect(s, x, y + 0.02, 0.06, 0.22, color)
    add_text(s, x + 0.14, y, w, 0.26, text, size=10.2, color=color, bold=True)


def table(s, x, y, w, headers, rows, widths, row_h=0.36, font=7.8,
          lost_col=None, note_col=None):
    nrows, ncols = len(rows) + 1, len(headers)
    h = 0.32 + len(rows) * row_h
    tbl = s.shapes.add_table(nrows, ncols, Inches(x), Inches(y), Inches(w), Inches(h)).table
    tbl.first_row = True; tbl.horz_banding = False
    for j, wd in enumerate(widths):
        tbl.columns[j].width = Inches(wd)
    tbl.rows[0].height = Inches(0.32)
    for i in range(1, nrows):
        tbl.rows[i].height = Inches(row_h)
    for j, htext in enumerate(headers):
        cell = tbl.cell(0, j)
        cell.fill.solid(); cell.fill.fore_color.rgb = NAVY
        cell.margin_left = Inches(0.04); cell.margin_right = Inches(0.035)
        cell.margin_top = cell.margin_bottom = Inches(0.01)
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
        p = cell.text_frame.paragraphs[0]
        p.alignment = PP_ALIGN.CENTER if j else PP_ALIGN.LEFT
        r = p.add_run(); r.text = htext; set_run(r, 7.5, WHITE, True)
    for i, row in enumerate(rows, start=1):
        fill = PALE if i % 2 == 0 else WHITE
        for j, val in enumerate(row):
            cell = tbl.cell(i, j)
            cell.fill.solid(); cell.fill.fore_color.rgb = fill
            cell.margin_left = Inches(0.04); cell.margin_right = Inches(0.035)
            cell.margin_top = cell.margin_bottom = Inches(0.01)
            cell.vertical_anchor = MSO_ANCHOR.MIDDLE
            p = cell.text_frame.paragraphs[0]
            p.alignment = PP_ALIGN.CENTER if j in (1, 2, 3) else PP_ALIGN.LEFT
            p.line_spacing = 1.0
            r = p.add_run(); r.text = str(val)
            color = NAVY
            if lost_col is not None and j == lost_col and str(val).startswith('丢失'):
                color = RED
            if note_col is not None and j == note_col:
                color = GREY
            set_run(r, font, color, j == 0)
    return tbl


def add_footer(s, note):
    add_rect(s, 0.48, 7.02, 12.35, 0.012, RGBColor(0xD9, 0xE2, 0xEE))
    add_text(s, 0.48, 7.10, 9.9, 0.22, note, size=6.9, color=MIDGREY)
    add_text(s, 10.55, 7.10, 2.25, 0.22, '守护生命健康，缔造美好生活', size=7.5, color=BLUE, bold=True, align=PP_ALIGN.RIGHT)


prs = Presentation(SRC)
blank = prs.slide_layouts[1]
new_ids = []


def new_slide(name):
    s = prs.slides.add_slide(blank)
    for shape in list(s.shapes):
        if shape.is_placeholder:
            shape._element.getparent().remove(shape._element)
    add_header(s, name)
    new_ids.append(prs.slides._sldIdLst[-1])
    return s

# ---------------- 赵云浩 ----------------
s = new_slide('赵云浩')
add_cards(s, '2 个', '564.67→170.50', '新增客户', ('7 户', '4.38 万'))
add_panel_title(s, 0.48, 2.18, 6.1, '丢失商机｜2025→2026 下降 >50%', RED)
table(s, 0.48, 2.48, 6.25,
      ['集团/归口', '2025', '2026 1-10', '同比', '主要下降客户'],
      [['圣湘集团', '559.82', '168.21', '30.0%', '圣湘生物 468.92→75.04；圣维鲲腾两主体归零'],
       ['华之源', '4.85', '2.29', '47.1%', '同比下降 52.9%，小额客户']],
      [1.55, 0.82, 0.95, 0.68, 2.25], row_h=0.64, font=7.4, note_col=4)
add_text(s, 0.48, 4.32, 6.2, 0.24, '丢失额合计：2025 564.67 → 2026 170.50，整体 30.2%', size=8.2, color=RED, bold=True)

add_panel_title(s, 6.95, 2.18, 5.8, '新增商机｜2025 无销售、2026 有销售', GREEN)
table(s, 6.95, 2.48, 5.78,
      ['客户/主体', '2026 1-10', '备注'],
      [['郑州海关技术中心', '1.50', '新客户'],
       ['东北农业大学', '1.00', '新客户'],
       ['新疆农业大学', '1.00', '新客户'],
       ['河南蓄诚生物', '0.69', '新客户'],
       ['郑州崇源科贸', '0.08', '新客户'],
       ['长沙索科亚', '0.07', '新客户'],
       ['洛阳助尔生物', '0.04', '新客户']],
      [2.55, 1.05, 1.85], row_h=0.36, font=7.6)
add_text(s, 6.95, 5.42, 5.8, 0.55,
         '新增销售合计 4.38 万；其余 0.04 万以下未单列。\n新项目储备：科蒂亚（新客户开发）尚在接洽。',
         size=7.5, color=GREY)
add_footer(s, '口径：2025年销售额取全年价税合计；2026为1-10月；集团归口按大客户2清单；新增按客户主体，不含2025有销售客户。')

# ---------------- 刘子研 ----------------
s = new_slide('刘子研')
add_cards(s, '2 个', '395.26→160.37', '新增客户', ('2 户', '4.34 万'))
add_panel_title(s, 0.48, 2.18, 6.1, '丢失商机｜2025→2026 下降 >50%', RED)
table(s, 0.48, 2.48, 6.25,
      ['集团/归口', '2025', '2026 1-10', '同比', '主要下降客户'],
      [['天隆集团', '320.43', '152.75', '47.7%', '西安华伟 164.23→84.81；苏州天隆 95.13→51.06；含雅为/陆军'],
       ['海尔施集团', '74.83', '7.62', '10.2%', '宁波海尔施 73.31→4.83']],
      [1.55, 0.82, 0.95, 0.68, 2.25], row_h=0.80, font=7.2, note_col=4)
add_text(s, 0.48, 4.60, 6.2, 0.24, '丢失额合计：2025 395.26 → 2026 160.37，整体 40.6%', size=8.2, color=RED, bold=True)

add_panel_title(s, 6.95, 2.18, 5.8, '新增商机｜2025 无销售、2026 有销售', GREEN)
table(s, 6.95, 2.48, 5.78,
      ['客户/主体', '2026 销售', '备注'],
      [['上海之江生物', '3.45', '11/4 首单，超1-10月窗口'],
       ['珠海丽禾医疗', '0.89', '丽珠集团，新客户'],
       ['上海科华生物', '—', '血筛 M4211-3/Tth 在测'],
       ['艾德生物', '—', '肿瘤 SNP 资料/方案']],
      [2.35, 1.00, 2.10], row_h=0.44, font=7.4, note_col=2)
add_text(s, 6.95, 4.72, 5.8, 0.55,
         '已形成销售新增 4.34 万；其中之江 3.45 万为11/4订单，超出1-10月统计窗，单列。\n科华、艾德为2026新项目，尚无销售。',
         size=7.3, color=GREY)
add_footer(s, '口径：2025年销售额取全年价税合计；2026为1-10月，之江首单11/4单列；集团归口按大客户1清单，雅为/陆军并入天隆；新增按客户主体。')

# 插入到P11之后（索引11之后）
sldIdLst = prs.slides._sldIdLst
for offset, new_id in enumerate(new_ids):
    sldIdLst.remove(new_id)
    sldIdLst.insert(12 + offset, new_id)

# 更新归纳页页码引用
for slide in prs.slides:
    for sh in slide.shapes:
        if sh.has_text_frame:
            for p in sh.text_frame.paragraphs:
                for r in p.runs:
                    if 'P8–P21' in r.text:
                        r.text = r.text.replace('P8–P21', 'P8–P23')

prs.save(SRC)
print('saved in place', SRC)
print('slides', len(prs.slides))
