#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""在v7中插入赵云浩、刘子研大客户丢失Y1集团口径明细各一页。"""
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.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)


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}｜大客户丢失 Y1（集团口径）', size=18, color=NAVY, bold=True)
    add_text(s, 0.48, 1.02, 12.3, 0.28,
             '2026年1-10月 vs 2025全年｜丢失=2026年1-10月 < 2025全年×80%｜单位：万元',
             size=8.8, color=GREY)


def add_cards(s, groups, lost, kept, coeff):
    items = [('集团数', str(groups), BLUE), ('丢失', str(lost), RED),
             ('保有', str(kept), GREEN), ('Y1 系数', str(coeff), NAVY)]
    for (label, value, color), x in zip(items, [0.48, 3.55, 6.62, 9.69]):
        add_rect(s, x, 1.42, 2.78, 0.68, PALE, line=RGBColor(0xDD, 0xE7, 0xF2), radius=True)
        add_text(s, x + 0.18, 1.49, 2.45, 0.18, label, size=7.8, color=GREY)
        add_text(s, x + 0.18, 1.67, 2.45, 0.30, value, size=15, color=color, bold=True)


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=7.0, color=MIDGREY)
    add_text(s, 10.55, 7.10, 2.25, 0.22, '守护生命健康，缔造美好生活', size=7.5, color=BLUE, bold=True, align=PP_ALIGN.RIGHT)


def add_table(s, rows, total_line, font_size=8.0, row_height=0.28):
    headers = ['集团/归口', '2025全年', '2026年1-10月', '同比', '判定']
    widths = [3.6, 1.55, 1.65, 1.1, 1.2]
    nrows, ncols = len(rows) + 1, len(headers)
    x, y, w, h = 0.48, 2.32, 9.1, 0.34 + len(rows) * row_height
    table = s.shapes.add_table(nrows, ncols, Inches(x), Inches(y), Inches(w), Inches(h)).table
    table.first_row = True
    table.horz_banding = False
    for j, wd in enumerate(widths):
        table.columns[j].width = Inches(wd)
    table.rows[0].height = Inches(0.32)
    for i in range(1, nrows):
        table.rows[i].height = Inches(row_height)
    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.01); 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, 4) else PP_ALIGN.LEFT
        r = p.add_run(); r.text = htext
        set_run(r, 7.9, WHITE, True)
    for i, row in enumerate(rows, start=1):
        lost = str(row[4]).startswith('丢失')
        fill = RGBColor(0xFD, 0xEC, 0xEA) if lost else (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.01); 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, 4) else PP_ALIGN.LEFT
            r = p.add_run(); r.text = str(val)
            color = RED if j == 4 and lost else (GREEN if j == 4 else NAVY)
            set_run(r, font_size, color, j == 0)
    # total line right of table
    add_text(s, 9.85, 2.40, 3.0, 0.25, '合计', size=9, color=BLUE, bold=True)
    add_text(s, 9.85, 2.68, 3.0, 0.8, total_line, size=8.4, color=NAVY, line_spacing=1.2)


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

# 赵云浩 15 groups, lost 4
s = new_slide('赵云浩')
add_cards(s, 15, 4, 11, '0.5')
rows = [
    ['圣湘集团', '559.82', '168.21', '30.0%', '丢失'],
    ['明德集团', '51.90', '35.30', '68.0%', '丢失'],
    ['中道集团', '10.88', '8.41', '77.3%', '丢失'],
    ['河南省华之源', '4.85', '2.29', '47.1%', '丢失'],
    ['万孚集团', '102.78', '144.22', '140.3%', '保有'],
    ['北京明日达', '87.23', '73.85', '84.7%', '保有'],
    ['洛阳普泰', '31.60', '32.30', '102.2%', '保有'],
    ['安图集团', '21.88', '20.32', '92.9%', '保有'],
    ['郑州纳克', '18.48', '41.75', '226.0%', '保有'],
    ['深圳芯思', '7.41', '8.39', '113.2%', '保有'],
    ['欣中生物', '4.38', '12.29', '280.5%', '保有'],
    ['许昌学院', '1.91', '5.30', '277.5%', '保有'],
    ['潮州凯普', '1.80', '3.25', '180.7%', '保有'],
    ['爱森集团', '0.57', '0.60', '105.3%', '保有'],
    ['河南农业大学', '0.10', '0.55', '581.5%', '保有'],
]
add_table(s, rows, '2025全年 905.59\n2026年1-10月 557.03\n整体 61.5%\n丢失 4/15，保有 11/15')
add_footer(s, '口径：大客户2清单集团归口；2025全年订单价税合计；2026为1-10月；未计2025无销售集团。')

# 刘子研 11 groups, lost 5
s = new_slide('刘子研')
add_cards(s, 11, 5, 6, '0.5')
rows = [
    ['天隆集团', '259.36', '135.88', '52.4%', '丢失'],
    ['佰奥莱博集团', '111.01', '84.40', '76.0%', '丢失'],
    ['海尔施集团', '74.83', '7.62', '10.2%', '丢失'],
    ['深圳市雅为世纪', '56.07', '16.87', '30.1%', '丢失'],
    ['陆军军医大学第一附属医院', '5.00', '0.00', '0.0%', '丢失'],
    ['丽珠集团', '240.81', '240.49', '99.9%', '保有'],
    ['苏州华益美', '83.43', '70.11', '84.0%', '保有'],
    ['东方基因集团', '39.93', '65.70', '164.5%', '保有'],
    ['复星集团', '24.93', '51.72', '207.5%', '保有'],
    ['杭州迪安', '13.82', '32.95', '238.3%', '保有'],
    ['深圳市新产业', '2.28', '9.28', '406.7%', '保有'],
]
add_table(s, rows, '2025全年 911.47\n2026年1-10月 715.02\n整体 78.4%\n丢失 5/11，保有 6/11', font_size=8.4, row_height=0.38)
add_footer(s, '口径：大客户1清单集团归口；2025全年订单价税合计；2026为1-10月；未计2025无销售集团。')

# insert after P9 (index 9)
sldIdLst = prs.slides._sldIdLst
for offset, new_id in enumerate(new_ids):
    sldIdLst.remove(new_id)
    sldIdLst.insert(9 + offset, new_id)

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