from pptx import Presentation
from pptx.util import Inches, Pt, Cm
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.enum.text import MSO_ANCHOR  # 导入正确的垂直对齐枚举
from pptx.enum.shapes import MSO_SHAPE
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.table import Table

def apply_gradient_background(slide):
    """应用统一的渐变背景"""
    background = slide.background
    fill = background.fill
    fill.gradient()
    fill.gradient_stops[0].color.rgb = RGBColor(0, 32, 96)    # 深蓝
    fill.gradient_stops[1].color.rgb = RGBColor(0, 112, 192)  # 蓝色

def create_content_slide(prs, title_text, subtitle_text=None, content_items=None):
    """创建带二级标题的内容页"""
    slide_layout = prs.slide_layouts[6]  # 空白布局
    slide = prs.slides.add_slide(slide_layout)
    apply_gradient_background(slide)
    
    # 添加主标题
    left = Cm(1.5)
    top = Cm(1.5)
    width = Cm(10)
    height = Cm(2)
    title_box = slide.shapes.add_textbox(left, top, width, height)
    tf = title_box.text_frame
    tf.clear()
    
    p = tf.add_paragraph()
    p.text = title_text
    p.font.size = Pt(36)
    p.font.color.rgb = RGBColor(255, 255, 255)
    p.font.bold = True
    
    # 添加二级标题（如果有）
    if subtitle_text:
        left = Cm(1.5)
        top = Cm(3)
        width = Cm(10)
        height = Cm(1.5)
        subtitle_box = slide.shapes.add_textbox(left, top, width, height)
        tf = subtitle_box.text_frame
        tf.clear()
        
        p = tf.add_paragraph()
        p.text = subtitle_text
        p.font.size = Pt(24)
        p.font.color.rgb = RGBColor(200, 230, 255)  # 浅蓝色
        p.font.italic = True
    
    # 添加内容区域
    if content_items:
        # 添加内容文字
        left_text = Cm(2)
        top_text = Cm(5.5 if subtitle_text else 4.5)
        width_text = Cm(27.5)
        height_text = Cm(8)
        text_box = slide.shapes.add_textbox(left_text, top_text, width_text, height_text)
        tf = text_box.text_frame
        tf.clear()
        
        for item in content_items:
            p = tf.add_paragraph()
            p.text = item["text"]
            p.font.size = Pt(item.get("size", 18))
            p.font.color.rgb = RGBColor(255, 255, 255)
            p.space_after = Pt(item.get("space_after", 8))
            p.level = item.get("level", 0)
            if item.get("bold", False):
                p.font.bold = True
            if item.get("bullet", False):
                p.text = "• " + p.text
    
    return slide

def create_table_slide(prs, title_text, subtitle_text, headers, data):
    """创建带表格的数据页"""
    slide = create_content_slide(prs, title_text, subtitle_text)
    
    # 计算表格位置和大小
    left = Cm(2)
    top = Cm(5.5 if subtitle_text else 4.5)
    width = Cm(26.5)
    height = Cm(8)
    
    # 创建表格 (行数=数据行数+1，列数=标题数)
    rows = len(data) + 1
    cols = len(headers)
    table = slide.shapes.add_table(rows, cols, left, top, width, height).table
    
    # 设置表格样式
    table.first_row = True  # 强调第一行
    table.horz_banding = True  # 横向条纹
    
    # 设置表头
    for col_idx, header in enumerate(headers):
        cell = table.cell(0, col_idx)
        cell.text = header
        cell.fill.solid()
        cell.fill.fore_color.rgb = RGBColor(0, 64, 128)  # 深蓝色表头
        cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255)
        cell.text_frame.paragraphs[0].font.bold = True
        cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
    
    # 填充表格数据
    for row_idx, row_data in enumerate(data, start=1):
        for col_idx, cell_data in enumerate(row_data):
            cell = table.cell(row_idx, col_idx)
            cell.text = str(cell_data)
            cell.fill.solid()
            cell.fill.fore_color.rgb = RGBColor(255, 255, 255)
            cell.fill.fore_color.alpha = 0.2  # 半透明白色
            cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)  # 黑色文字
            cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
    
    # 设置表格边框
    for cell in table.iter_cells():
        cell.margin_left = Cm(0.1)
        cell.margin_right = Cm(0.1)
        cell.margin_top = Cm(0.05)
        cell.margin_bottom = Cm(0.05)
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
    
    return slide


def create_chart_slide(prs, title_text, subtitle_text, categories, data):
    """创建图表的数据页"""
    slide = create_content_slide(prs, title_text, subtitle_text)
    
    #半透明白色背景
    left_content = Cm(1.5)
    top_content = Cm(5 if subtitle_text else 4)  # 根据是否有二级标题调整位置
    width_content = Cm(28.5)
    height_content = Cm(9)
    content_box = slide.shapes.add_shape(
        MSO_SHAPE.ROUNDED_RECTANGLE, left_content, top_content, width_content, height_content
    )
    content_box.fill.solid()
    content_box.fill.fore_color.rgb = RGBColor(255, 255, 255)
    content_box.fill.fore_color.alpha = 0.2  # 20%透明度
    content_box.line.color.rgb = RGBColor(200, 230, 255)
        
    # 添加图表数据
    chart_data = ChartData()
    chart_data.categories = categories
    for lable_data in data:
        chart_data.add_series(lable_data[0], lable_data[1])
    
    # 添加图表
    left_chart = Cm(3)
    top_chart = Cm(6)
    width_chart = Cm(25)
    height_chart = Cm(7)
    chart = slide.shapes.add_chart(
        XL_CHART_TYPE.LINE, left_chart, top_chart, width_chart, height_chart, chart_data
    )
    
    # 设置图表颜色以匹配主题
    chart.chart.plots[0].series[0].format.fill.solid()
    chart.chart.plots[0].series[0].format.fill.fore_color.rgb = RGBColor(100, 180, 255)
    chart.chart.plots[0].series[1].format.fill.solid()
    chart.chart.plots[0].series[1].format.fill.fore_color.rgb = RGBColor(200, 230, 255)
    
    return slide
    



def create_image_layout_slide(prs, title_text, subtitle_text, images):
    """创建图片布局页面"""
    slide = create_content_slide(prs, title_text, subtitle_text)
    
    # 清除默认内容区域
    for shape in slide.shapes:
        if shape.shape_type == MSO_SHAPE.ROUNDED_RECTANGLE:
            sp = shape._element
            sp.getparent().remove(sp)
    
    # 根据图片数量决定布局
    if len(images) == 1:
        # 单张大图布局
        left = Cm(3)
        top = Cm(5 if subtitle_text else 4)
        width = Cm(25)
        height = Cm(12)
        pic = slide.shapes.add_picture(images[0]["path"], left, top, width, height)
        
        # 添加图片说明
        if "caption" in images[0]:
            left_cap = Cm(3)
            top_cap = Cm(17 if subtitle_text else 16)
            width_cap = Cm(25)
            height_cap = Cm(1)
            cap = slide.shapes.add_textbox(left_cap, top_cap, width_cap, height_cap)
            tf = cap.text_frame
            p = tf.add_paragraph()
            p.text = images[0]["caption"]
            p.font.size = Pt(14)
            p.font.color.rgb = RGBColor(200, 230, 255)
            p.alignment = PP_ALIGN.CENTER
    
    elif len(images) == 2:
        # 两张图片并排布局
        # 第一张图片
        left1 = Cm(2)
        top1 = Cm(5 if subtitle_text else 4)
        width1 = Cm(13)
        height1 = Cm(12)
        pic1 = slide.shapes.add_picture(images[0]["path"], left1, top1, width1, height1)
        
        # 第二张图片
        left2 = Cm(16)
        top2 = Cm(5 if subtitle_text else 4)
        width2 = Cm(13)
        height2 = Cm(12)
        pic2 = slide.shapes.add_picture(images[1]["path"], left2, top2, width2, height2)
        
        # 添加图片说明
        for i, img in enumerate(images):
            if "caption" in img:
                left_cap = Cm(2 if i == 0 else 16)
                top_cap = Cm(17 if subtitle_text else 16)
                width_cap = Cm(13)
                height_cap = Cm(1)
                cap = slide.shapes.add_textbox(left_cap, top_cap, width_cap, height_cap)
                tf = cap.text_frame
                p = tf.add_paragraph()
                p.text = img["caption"]
                p.font.size = Pt(12)
                p.font.color.rgb = RGBColor(200, 230, 255)
                p.alignment = PP_ALIGN.CENTER
    
    elif len(images) >= 3:
        # 三张图片网格布局
        img_size = Cm(8)
        gap = Cm(1)
        
        # 第一行
        for i in range(min(3, len(images))):
            left = Cm(3) + (img_size + gap) * i
            top = Cm(5 if subtitle_text else 4)
            pic = slide.shapes.add_picture(images[i]["path"], left, top, img_size, img_size)
            
            if "caption" in images[i]:
                left_cap = left
                top_cap = top + img_size + Cm(0.5)
                width_cap = img_size
                height_cap = Cm(1)
                cap = slide.shapes.add_textbox(left_cap, top_cap, width_cap, height_cap)
                tf = cap.text_frame
                p = tf.add_paragraph()
                p.text = images[i]["caption"]
                p.font.size = Pt(10)
                p.font.color.rgb = RGBColor(200, 230, 255)
                p.alignment = PP_ALIGN.CENTER
        
        # 第二行（如果有4张以上图片）
        img_size = Cm(4)
        gap = Cm(1)
        for i in range(3, len(images)):
            left = Cm(3) + (img_size + gap) * (i - 3)
            top = Cm(16 if subtitle_text else 15)
            pic = slide.shapes.add_picture(images[i]["path"], left, top, img_size, img_size)
            
            if "caption" in images[i]:
                left_cap = left
                top_cap = top + img_size + Cm(0.5)
                width_cap = img_size
                height_cap = Cm(1)
                cap = slide.shapes.add_textbox(left_cap, top_cap, width_cap, height_cap)
                tf = cap.text_frame
                p = tf.add_paragraph()
                p.text = images[i]["caption"]
                p.font.size = Pt(10)
                p.font.color.rgb = RGBColor(200, 230, 255)
                p.alignment = PP_ALIGN.CENTER
    
    return slide

def create_unified_ppt(output_filename):
    # 创建一个16:9宽屏演示文稿对象
    prs = Presentation()
    #prs.slide_width = Inches(13.333)  # 16:9的宽度
    #prs.slide_height = Inches(7.5)    # 16:9的高度

    prs.slide_width = Inches(16)  # 16:9的宽度
    prs.slide_height = Inches(9)    # 16:9的高度
    
    # ===== 封面幻灯片 =====
    slide_layout = prs.slide_layouts[6]  # 空白布局
    slide = prs.slides.add_slide(slide_layout)
    apply_gradient_background(slide)
    
    # 添加宽屏标题
    left = Cm(1.5)
    top = Cm(4)
    width = Cm(30)
    height = Cm(4)
    title_box = slide.shapes.add_textbox(left, top, width, height)
    tf = title_box.text_frame
    
    p = tf.add_paragraph()
    p.text = "专业商务演示"
    p.font.size = Pt(48)
    p.font.color.rgb = RGBColor(255, 255, 255)
    p.font.bold = True
    p.alignment = PP_ALIGN.LEFT
    
    # 添加副标题
    left = Cm(1.5)
    top = Cm(8)
    width = Cm(20)
    height = Cm(2)
    subtitle_box = slide.shapes.add_textbox(left, top, width, height)
    tf = subtitle_box.text_frame
    
    p = tf.add_paragraph()
    p.text = "包含表格和图片布局的演示文稿"
    p.font.size = Pt(20)
    p.font.color.rgb = RGBColor(200, 230, 255)
    p.alignment = PP_ALIGN.LEFT
    
    # ===== 目录幻灯片 =====
    create_content_slide(
        prs,
        "内容目录",
        content_items=[
            {"text": "1. 项目概述", "size": 24, "space_after": 12},
            {"text": "2. 市场分析", "size": 24, "space_after": 12},
            {"text": "3. 财务数据", "size": 24, "space_after": 12},
            {"text": "4. 产品展示", "size": 24, "space_after": 12},
            {"text": "5. 技术架构", "size": 24, "space_after": 12}
        ]
    )
    
    # ===== 一级标题内容页 =====
    create_content_slide(
        prs,
        "项目概述",
        content_items=[
            {"text": "项目背景", "size": 22, "bold": True, "space_after": 8},
            {"text": "随着数字化转型加速，企业需要更高效的解决方案来应对市场变化。", "bullet": True},
            {"text": "本项目旨在开发一套智能化管理系统，提升企业运营效率。", "bullet": True},
            {"text": "项目目标", "size": 22, "bold": True, "space_after": 8, "space_before": 12},
            {"text": "构建可扩展的技术架构，支持未来5年业务增长", "bullet": True},
            {"text": "实现关键业务流程自动化，减少人工干预", "bullet": True},
            {"text": "提供数据分析和决策支持功能", "bullet": True}
        ]
    )
    
    # ===== 带二级标题的内容页 =====
    create_content_slide(
        prs,
        "技术架构",
        "核心技术组件",  # 二级标题
        content_items=[
            {"text": "前端技术", "size": 22, "bold": True, "space_after": 8},
            {"text": "采用React框架构建响应式用户界面", "bullet": True},
            {"text": "使用TypeScript提高代码质量", "bullet": True},
            {"text": "后端技术", "size": 22, "bold": True, "space_after": 8, "space_before": 12},
            {"text": "基于Spring Boot的微服务架构", "bullet": True},
            {"text": "使用Kubernetes进行容器编排", "bullet": True},
            {"text": "数据库技术", "size": 22, "bold": True, "space_after": 8, "space_before": 12},
            {"text": "主数据库: PostgreSQL 14", "bullet": True},
            {"text": "缓存层: Redis集群", "bullet": True},
            {"text": "数据分析: Elasticsearch", "bullet": True}
        ]
    )
    # ===== 表格数据页面 =====
    headers = ["季度", "营收(万元)", "同比增长", "利润率", "市场份额"]
    data = [
        ["Q1 2023", 1250, "12.5%", "18.2%", "22.4%"],
        ["Q2 2023", 1430, "15.8%", "19.1%", "23.7%"],
        ["Q3 2023", 1580, "18.2%", "20.3%", "25.1%"],
        ["Q4 2023", 1720, "20.1%", "21.5%", "26.8%"],
        ["Q1 2024", 1850, "22.7%", "22.8%", "28.3%"]
    ]
    create_table_slide(
        prs,
        "财务数据",
        "2023-2024季度表现",
        headers,
        data
    )
    
    # ===== 图片布局页面（单张大图）=====
    create_image_layout_slide(
        prs,
        "产品展示",
        "旗舰产品全景",
        [{
            "path": "product.jpg",  # 替换为实际图片路径
            "caption": "图1: 公司旗舰产品XYZ系列"
        }]
    )
    
    # ===== 图片布局页面（两张并排）=====
    create_image_layout_slide(
        prs,
        "技术对比",
        "新旧技术方案比较",
        [
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "图2: 传统技术方案"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "图3: 创新技术方案"
            }
        ]
    )
    
    # ===== 图片布局页面（三栏）=====
    create_image_layout_slide(
        prs,
        "应用场景",
        "多领域解决方案",
        [
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "工业制造"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "金融服务"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "医疗健康"
            },
        ]
    )
    # ===== 图片布局页面（多栏）=====
    create_image_layout_slide(
        prs,
        "应用场景",
        "多领域解决方案",
        [
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "工业制造"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "金融服务"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "医疗健康"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "医疗健康"
            },
            {
                "path": "product.jpg",  # 替换为实际图片路径
                "caption": "医疗健康"
            },
        ]
    )

    # ===== 图表幻灯片 =====
    slide = create_chart_slide(
        prs,
        "市场分析",
        "近五年增长趋势",  # 二级标题
        categories = ['2019', '2020', '2021', '2022', '2023'],
        data = [
            ['市场规模(亿元)', [45, 52, 61, 78, 92]],
            ['年增长率(%)', [8.2, 15.6, 17.3, 27.9, 17.9]],
        ]
    )
    
    # ===== 结束幻灯片 =====
    slide = create_content_slide(
        prs,
        "感谢聆听",
        "期待与您合作"
    )
    
    # 在内容区域添加联系信息
    left = Cm(12)
    top = Cm(12)
    width = Cm(16)
    height = Cm(3)
    contact_box = slide.shapes.add_textbox(left, top, width, height)
    tf = contact_box.text_frame
    
    p = tf.add_paragraph()
    p.text = "联系方式"
    p.font.size = Pt(24)
    p.font.color.rgb = RGBColor(255, 255, 255)
    p.font.bold = True
    p.alignment = PP_ALIGN.CENTER
    p.space_after = Pt(16)
    
    p = tf.add_paragraph()
    p.text = "邮箱: contact@example.com\n电话: 123-456-7890\n网址: www.example.com"
    p.font.size = Pt(18)
    p.font.color.rgb = RGBColor(200, 230, 255)
    p.alignment = PP_ALIGN.CENTER
    p.space_before = Pt(8)
    
    # 保存演示文稿
    prs.save(output_filename)

if __name__ == "__main__":
    # 使用前请替换示例图片路径为实际图片路径
    create_unified_ppt("professional_presentation_with_tables_and_images.pptx")
    print("带表格和图片布局的PPT生成完成!")
