#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""在10月汇报PPT的11月目标页后，增加“11月待办：仍未推动的卡点”。"""
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_v4.pptx')
OUT = os.path.join(ROOT, '经营分析/月报/2026年10月销售部工作汇报_草稿_20261108_v5.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)
AMBER = RGBColor(0xB7, 0x79, 0x1F)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)


def set_run(run, size=8.5, 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.08):
    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)
    return box


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
    return shp


prs = Presentation(SRC)
blank = prs.slide_layouts[1]
s = prs.slides.add_slide(blank)
for shape in list(s.shapes):
    if shape.is_placeholder:
        shape._element.getparent().remove(shape._element)

# header
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.60, 12.0, 0.42, '11月待办：仍未推动的卡点', size=18, color=NAVY, bold=True)
add_text(s, 0.48, 1.03, 12.3, 0.28,
         '来源：大客户部 10 月月会纪要（2026-11-02）｜只列无进度、等待外部或资料未齐的事项',
         size=9.2, color=GREY)

rows = [
    ['明日达\n829 冻干',
     '液体性能提升；冻干后仍不如对照，37℃ 5d 更差；客户物料无阳性质粒。',
     '冻干后性能/耐抑制未解；无阳性样本，成品验证无法闭环。',
     '内部先出冻干成品；向客户要阳性质粒或替代阳性样本；本周上机。',
     '赵云浩 / 技术支持\n11/30'],
    ['明日达\nM2244-043801',
     '低浓度 Ct33 荧光增量 -20% 仍放行；客户实测 Ct35 灵敏度下降。',
     '放行标准低于行业灵敏度要求，客诉未闭环。',
     '提升低浓度放行标准；复测历史批次；质量+研发联合评审。',
     '赵云浩 / 质量\n11/30'],
    ['圣湘\n公卫/海外 RT 预混',
     '2–3 个月无正向优化；37℃ 3–7 天加速不如诺唯赞；中期评审拟关闭项目。',
     '稳定性窗口错过；项目面临关闭，但方向不能停。',
     '中期评审保留方向；重排 37℃ 加速配方；争取客户再送测。',
     '刘子研 / 研发\n11/30'],
    ['圣湘\nM2181-4-NA-095203',
     '质量协议卡住：客户要求明确 16S/18S 覆盖的微生物种类及出厂放行标准。',
     '质量条款未定，影响供货与协议签署。',
     '质量+研发出覆盖清单与放行标准；与客户逐条对齐。',
     '刘子研 / 质量\n11/30'],
    ['丹威\nLAMP 冻干全预混',
     '上周样品稳定性客户尚未反馈；全预混 4h（2–8℃）稳定性仍在优化。',
     '等待客户测试，内部优化无法闭环。',
     '催刘老师本周反馈；内部同步做加速；约现场复盘。',
     '刘子研 / 技术支持\n11/30'],
    ['新产业\nHIV 项目',
     '研发要等客户阳性模板才试验；内部阴性初筛尚未启动。',
     '项目被外部样本卡住，时间不可控。',
     '先用阴性做翘尾/假阳初筛，再做阳性验证；本周启动。',
     '刘子研 / 研发\n11/30'],
    ['艾德\n肿瘤 SNP',
     '需 Takara 同位素法测活对标说明、多批次测活数据；春芳/何弦资料未齐。',
     '数据未齐，无法形成客户测试方案。',
     '11月收齐数据表；发客户；约研发现场/线上交流。',
     '刘子研 / 春芳 / 何弦\n11/30'],
]

# table
nrows, ncols = len(rows) + 1, 5
table = s.shapes.add_table(nrows, ncols, Inches(0.48), Inches(1.45), Inches(12.4), Inches(5.15)).table
table.first_row = True
table.horz_banding = False
widths = [1.55, 3.15, 2.55, 3.85, 1.30]
for j, wd in enumerate(widths):
    table.columns[j].width = Inches(wd)
table.rows[0].height = Inches(0.40)
for i in range(1, nrows):
    table.rows[i].height = Inches(0.68)

headers = ['客户/事项', '当前进度', '卡点', '11月动作', '责任人/时间']
for j, htext in enumerate(headers):
    cell = table.cell(0, j)
    cell.fill.solid(); cell.fill.fore_color.rgb = NAVY
    cell.margin_left = Inches(0.05); cell.margin_right = Inches(0.04)
    cell.margin_top = Inches(0.02); cell.margin_bottom = Inches(0.02)
    cell.vertical_anchor = MSO_ANCHOR.MIDDLE
    p = cell.text_frame.paragraphs[0]
    p.alignment = PP_ALIGN.CENTER if j in (0, 4) else PP_ALIGN.LEFT
    r = p.add_run(); r.text = htext
    set_run(r, 8.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 = table.cell(i, j)
        cell.fill.solid(); cell.fill.fore_color.rgb = fill
        cell.margin_left = Inches(0.05); cell.margin_right = Inches(0.04)
        cell.margin_top = Inches(0.02); cell.margin_bottom = Inches(0.02)
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
        p = cell.text_frame.paragraphs[0]
        p.alignment = PP_ALIGN.CENTER if j in (0, 4) else PP_ALIGN.LEFT
        p.line_spacing = 1.02
        r = p.add_run(); r.text = str(val)
        color = NAVY
        bold = j == 0
        if j == 2:
            color = RED
        set_run(r, 8.2, color, bold)

# note
add_rect(s, 0.48, 6.78, 12.4, 0.20, WHITE)
add_text(s, 0.48, 6.82, 12.2, 0.2,
         '说明：回款、11月重点拜访、2027计划V2等正常推进事项未列入本页；销售拓展部10月月会纪要未在目录找到。',
         size=7.2, color=MIDGREY)
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, '来源：大客户部月会纪要 20261102；卡点判断按“无进度/等待外部/资料未齐”筛选。', size=7.1, color=MIDGREY)
add_text(s, 10.55, 7.10, 2.25, 0.22, '守护生命健康，缔造美好生活', size=7.5, color=BLUE, bold=True, align=PP_ALIGN.RIGHT)

# move new slide after P13 (index 13; current P13 is index 12)
sldIdLst = prs.slides._sldIdLst
new_id = sldIdLst[-1]
sldIdLst.remove(new_id)
sldIdLst.insert(13, new_id)

prs.save(OUT)
print('saved', OUT)
print('slides', len(prs.slides))
