from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_AUTO_SIZE, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.enum.text import MSO_ANCHOR

OUT = '/Users/bot1/Volumes/root_for_ai/AI工作区/西安博物院IP授权合作方工作说明_20260618_225024/授权合作说明_资料准备与合作流程.pptx'

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

# Palette
PAPER = RGBColor(255, 250, 241)
CARD = RGBColor(255, 253, 248)
LINE = RGBColor(232, 217, 199)
INK = RGBColor(37, 28, 23)
MUTED = RGBColor(108, 96, 88)
RED = RGBColor(152, 67, 43)
GOLD = RGBColor(182, 138, 72)
GREEN = RGBColor(37, 92, 86)
SOFT = RGBColor(255, 243, 226)
WHITE = RGBColor(255, 255, 255)

FONT_HEAD = 'Songti SC'
FONT_BODY = 'Microsoft YaHei'


def set_bg(slide, color=PAPER):
    bg = slide.background
    fill = bg.fill
    fill.solid()
    fill.fore_color.rgb = color


def add_text(slide, text, x, y, w, h, size=18, color=INK, bold=False, font=FONT_BODY,
             align=PP_ALIGN.LEFT, valign=MSO_ANCHOR.TOP, line_spacing=1.05):
    box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
    tf = box.text_frame
    tf.clear()
    tf.word_wrap = True
    tf.margin_left = Inches(0.02)
    tf.margin_right = Inches(0.02)
    tf.margin_top = Inches(0.02)
    tf.margin_bottom = Inches(0.02)
    tf.vertical_anchor = valign
    p = tf.paragraphs[0]
    p.alignment = align
    p.line_spacing = line_spacing
    run = p.add_run()
    run.text = text
    run.font.name = font
    run.font.size = Pt(size)
    run.font.bold = bold
    run.font.color.rgb = color
    return box


def add_title(slide, no, title, subtitle=None):
    add_text(slide, no, 0.65, 0.38, 0.65, 0.28, 11, RED, True, FONT_BODY)
    add_text(slide, title, 0.65, 0.66, 7.5, 0.55, 27, INK, True, FONT_HEAD)
    if subtitle:
        add_text(slide, subtitle, 0.68, 1.23, 8.8, 0.38, 12.5, MUTED, False, FONT_BODY)


def add_card(slide, x, y, w, h, title, body, label=None, label_color=RED, title_size=17, body_size=12.2):
    shp = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
    shp.fill.solid(); shp.fill.fore_color.rgb = CARD
    shp.line.color.rgb = LINE; shp.line.width = Pt(1)
    if label:
        lab = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x+0.22), Inches(y+0.22), Inches(0.78), Inches(0.32))
        lab.fill.solid(); lab.fill.fore_color.rgb = RGBColor(248, 238, 225)
        lab.line.color.rgb = RGBColor(248, 238, 225)
        add_text(slide, label, x+0.27, y+0.285, 0.68, 0.16, 9.5, label_color, True, FONT_BODY, align=PP_ALIGN.CENTER, valign=MSO_ANCHOR.MIDDLE)
        tx = x + 1.13; tw = w - 1.35
    else:
        tx = x + 0.25; tw = w - 0.5
    add_text(slide, title, tx, y+0.22, tw, 0.35, title_size, INK, True, FONT_BODY)
    add_text(slide, body, tx, y+0.66, tw, h-0.78, body_size, MUTED, False, FONT_BODY, line_spacing=1.05)
    return shp


def add_footer(slide):
    add_text(slide, '本文件用于授权合作前期沟通；最终安排以各方正式签署文件及书面确认为准。', 0.72, 7.08, 8.2, 0.22, 8.5, MUTED, False, FONT_BODY)

# Slide 1 Cover
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_bg(slide)
# decorative circles/shapes
circle = slide.shapes.add_shape(MSO_SHAPE.OVAL, Inches(10.15), Inches(0.12), Inches(2.75), Inches(2.75))
circle.fill.solid(); circle.fill.fore_color.rgb = SOFT; circle.line.color.rgb = SOFT
ring = slide.shapes.add_shape(MSO_SHAPE.ARC, Inches(10.02), Inches(0.02), Inches(3.0), Inches(3.0))
ring.line.color.rgb = RED; ring.line.transparency = 55; ring.line.width = Pt(14)
add_text(slide, 'Cooperation Brief', 0.8, 0.72, 2.8, 0.25, 12, GREEN, True, FONT_BODY)
add_text(slide, '授权合作说明', 0.78, 1.46, 6.6, 0.82, 42, INK, True, FONT_HEAD)
add_text(slide, '为便于后续与品牌方沟通，先将授权合作前需要了解的基础信息列在这里。可先按现有情况补充；暂时没有的信息，后续也可以根据具体项目再确认。', 0.82, 2.55, 7.4, 0.9, 18, RGBColor(75,58,49), False, FONT_BODY)
# key small chips directly business, not too directive
for i, (t, c) in enumerate([('资料准备', RED), ('合作方式', GREEN), ('签约与审核', GOLD)]):
    x = 0.82 + i*1.55
    chip = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(4.0), Inches(1.28), Inches(0.42))
    chip.fill.solid(); chip.fill.fore_color.rgb = RGBColor(255, 245, 232)
    chip.line.color.rgb = RGBColor(235, 220, 202)
    add_text(slide, t, x+0.12, 4.105, 1.04, 0.16, 11, c, True, FONT_BODY, align=PP_ALIGN.CENTER)
add_footer(slide)

# Slide 2 Materials
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '01', '需要提供和确认的资料', '以下内容用于初步判断合作范围、报价方式、签约路径和执行边界。')
materials = [
    ('提供', '完整授权链路', 'IP 方与贵方之间的授权书、合作协议或其他有效授权依据；如方便，可同步授权期限、授权范围和对外合作权限。', RED),
    ('提供', '商标注册清单', '可用于合作的商标名称、注册号、类别、权利人及有效状态。', RED),
    ('确认', '可授权图库 / 素材', '是否有可用于商业合作的图库、纹样、文物图像、建筑空间图片等；如已有目录或样张，可一并提供。', GREEN),
    ('确认', '专家 / 领导支持', '合作过程中是否可沟通领导，或安排专家参与内容指导、审稿、站台等；如可安排，再补充人员和参与边界。', GREEN),
    ('确认', '场地资源', '是否有可用于发布会、快闪、拍摄、线下活动等合作的场地资源；如已有门槛、费用或审批流程，可一并补充。', GREEN),
    ('可补充', '官方账号', '先确认有哪些官方账号可配合发布合作内容即可。发布形式、次数、审核要求等如已有规则，可一并补充。', GOLD),
]
for idx, item in enumerate(materials):
    x = 0.7 + (idx % 2) * 6.1
    y = 1.72 + (idx // 2) * 1.55
    add_card(slide, x, y, 5.72, 1.22, item[1], item[2], label=item[0], label_color=item[3], title_size=15.5, body_size=11.3)
add_footer(slide)

# Slide 3 Models
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '02', '合作方式', '不同项目可以采用不同商务机制，后续可根据品牌需求、授权深度和资源投入再沟通。')
# Two large comparison panels
for x, title, body, tags, color in [
    (0.76, '方式 A｜贵方报价 / 贵方主导定价', '我方提交品牌合作诉求，贵方根据授权范围、资源支持和审核要求出具报价。双方确认后，再推进品牌沟通、内部审批和签约。', ['适合标准授权','报价由贵方提供','我方推进客户沟通'], RED),
    (6.8, '方式 B｜我方定价 / 项目分成', '我方根据品牌预算、品类、渠道和合作内容制定对品牌的报价方案；项目给 IP 方或贵方的收益，可按固定比例或单项目另行沟通。', ['适合定制项目','报价由我方判断','收益按项目约定'], GREEN),
]:
    panel = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(1.8), Inches(5.76), Inches(3.65))
    panel.fill.solid(); panel.fill.fore_color.rgb = CARD
    panel.line.color.rgb = LINE; panel.line.width = Pt(1)
    band = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(1.8), Inches(0.16), Inches(3.65))
    band.fill.solid(); band.fill.fore_color.rgb = color; band.line.color.rgb = color
    add_text(slide, title, x+0.36, 2.15, 4.95, 0.52, 18.2, INK, True, FONT_BODY)
    add_text(slide, body, x+0.36, 2.9, 4.96, 1.02, 13.5, MUTED, False, FONT_BODY)
    for i, tg in enumerate(tags):
        chip = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x+0.36+i*1.62), Inches(4.55), Inches(1.44), Inches(0.36))
        chip.fill.solid(); chip.fill.fore_color.rgb = RGBColor(248, 238, 225)
        chip.line.color.rgb = RGBColor(248, 238, 225)
        add_text(slide, tg, x+0.43+i*1.62, 4.64, 1.3, 0.14, 9.0, color, True, FONT_BODY, align=PP_ALIGN.CENTER)
add_footer(slide)

# Slide 4 Contracting
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '03', '签约主体', '签约主体会影响授权链路、收款路径和合同责任，品牌合作前需要有清晰路径。')
contracts = [
    ('方案 1', '我方签约', '贵方先向我方提供转授权或合作授权依据，再由我方与品牌签约。', RED),
    ('方案 2', '贵方签约', '贵方作为授权主体与品牌签约，我方负责客户开发、商务推进和项目协同。', GREEN),
    ('方案 3', '按项目确定', '根据品牌要求、项目规模、收款路径和审批要求，单项目沟通签约主体。', GOLD),
]
for i, (label, title, body, color) in enumerate(contracts):
    x = 0.82 + i*4.12
    card = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(2.05), Inches(3.65), Inches(3.15))
    card.fill.solid(); card.fill.fore_color.rgb = CARD
    card.line.color.rgb = LINE
    oval = slide.shapes.add_shape(MSO_SHAPE.OVAL, Inches(x+0.28), Inches(2.38), Inches(0.78), Inches(0.78))
    oval.fill.solid(); oval.fill.fore_color.rgb = color
    oval.line.color.rgb = color
    add_text(slide, str(i+1), x+0.52, 2.57, 0.28, 0.2, 16, WHITE, True, FONT_BODY, align=PP_ALIGN.CENTER)
    add_text(slide, label, x+1.25, 2.34, 1.2, 0.24, 11.5, color, True, FONT_BODY)
    add_text(slide, title, x+1.25, 2.62, 1.9, 0.38, 19, INK, True, FONT_BODY)
    add_text(slide, body, x+0.32, 3.35, 3.0, 0.98, 13.2, MUTED, False, FONT_BODY)
add_footer(slide)

# Slide 5 Process
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '04', '项目推进流程', '以下流程用于帮助各方提前了解关键节点，便于后续合作推进。')
steps = [
    ('01','提交品牌诉求','我方提供品牌背景、合作目的、品类范围、所需资源和预计时间节点。'),
    ('02','沟通合作方式','根据项目情况沟通采用贵方报价，或采用我方定价、项目分成的方式。'),
    ('03','沟通签约主体','根据授权链路、收款路径和品牌要求，沟通签约主体。'),
    ('04','签约前置事项','正式签约前，先确定授权素材、审核负责人和沟通机制。'),
    ('05','内部审批','如需馆务会或 IP 方内部审批，应在品牌正式签约前完成。'),
    ('06','签约与项目启动','按已确认的素材、审核和沟通机制推进设计、打样、物料审核和发布配合。'),
]
for i, (no, title, body) in enumerate(steps):
    x = 0.74 + (i % 2)*6.12
    y = 1.62 + (i//2)*1.55
    color = RED if no == '04' else (GREEN if i % 2 else GOLD)
    shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(5.72), Inches(1.22))
    shape.fill.solid(); shape.fill.fore_color.rgb = CARD if no != '04' else RGBColor(255,248,238)
    shape.line.color.rgb = RGBColor(226,198,170) if no == '04' else LINE
    add_text(slide, no, x+0.24, y+0.24, 0.56, 0.32, 18, color, True, 'Georgia', align=PP_ALIGN.CENTER)
    add_text(slide, title, x+0.95, y+0.2, 3.9, 0.32, 15.5, INK, True, FONT_BODY)
    add_text(slide, body, x+0.95, y+0.58, 4.44, 0.42, 11.5, MUTED, False, FONT_BODY)
add_footer(slide)

# Slide 6 Review
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '05', '审核与执行事项', '以下事项不一定需要一次性全部确定，但建议在正式签约前形成基本共识。')
items = [
    ('授权素材', '可用于合作的图片、纹样、名称、标识、文案资料及其使用边界。'),
    ('审核负责人', '日常对接人、最终确认人，以及不同内容需要经过的审核层级。'),
    ('沟通机制', '项目群、沟通节奏、反馈方式、文件确认方式和紧急事项处理方式。'),
    ('审核范围', '产品设计、包装、宣传文案、电商页面、短视频脚本、海报物料等是否需要审核。'),
    ('审核时长', '常规反馈周期、紧急项目处理方式、修改轮次和最终确认方式。'),
    ('官方账号', '可配合发布合作内容的官方账号；如已有发布规则，可后续再补充。'),
    ('结算口径', '授权费、资源费、分成比例、固定比例或单项目协商方式。'),
]
# create 7 rows, split left 4 right 3
for i, (title, body) in enumerate(items):
    left = i < 4
    idx = i if left else i-4
    x = 0.78 if left else 6.85
    y = 1.72 + idx*1.16
    w = 5.56
    h = 0.88
    card = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
    card.fill.solid(); card.fill.fore_color.rgb = CARD
    card.line.color.rgb = LINE
    add_text(slide, title, x+0.24, y+0.19, 1.25, 0.28, 13.8, RED if i in [0,1,2] else GREEN, True, FONT_BODY)
    add_text(slide, body, x+1.56, y+0.17, w-1.82, 0.42, 11.2, MUTED, False, FONT_BODY)
add_footer(slide)

# Slide 7 Close / confirmation
slide = prs.slides.add_slide(prs.slide_layouts[6]); set_bg(slide)
add_title(slide, '06', '后续沟通重点', '可先按现有情况反馈，不需要一次性把所有细节都确定完。')
focus = [
    ('合作方式', '采用贵方报价，或采用我方定价、项目分成；也可按项目灵活沟通。'),
    ('签约主体', '由我方签约、贵方签约，或根据品牌项目单独确定。'),
    ('资料与资源', '授权链路、商标清单、图库素材、专家支持、场地资源、官方账号。'),
    ('审核机制', '授权素材、审核负责人、沟通机制以及基本审核周期。'),
]
for i, (t,b) in enumerate(focus):
    x = 1.05 + (i%2)*5.65
    y = 1.95 + (i//2)*1.65
    add_card(slide, x, y, 5.05, 1.24, t, b, label=None, title_size=17, body_size=12.2)
# Gentle closing note
note = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(1.04), Inches(5.65), Inches(11.2), Inches(0.66))
note.fill.solid(); note.fill.fore_color.rgb = RGBColor(255, 245, 232)
note.line.color.rgb = LINE
add_text(slide, '后续可根据具体品牌项目，再进一步细化报价、审批、审核和执行安排。', 1.35, 5.88, 9.6, 0.18, 14, RGBColor(73,54,44), False, FONT_BODY, align=PP_ALIGN.CENTER)
add_footer(slide)

prs.save(OUT)
print(OUT)
