from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
import json

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

# 配色
NAVY = RGBColor(15, 42, 68)
TEAL = RGBColor(22, 138, 143)
GOLD = RGBColor(215, 166, 66)
BG = RGBColor(245, 241, 232)
WHITE = RGBColor(255, 255, 255)
MUTED = RGBColor(93, 109, 126)

def add_bg(slide, color=BG):
    bg = slide.background
    fill = bg.fill
    fill.solid()
    fill.fore_color.rgb = color

def add_text(slide, left, top, width, height, text, font_size=18, color=NAVY, bold=True, alignment=PP_ALIGN.LEFT):
    txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = text
    p.font.size = Pt(font_size)
    p.font.color.rgb = color
    p.font.bold = bold
    p.alignment = alignment
    return txBox

def add_shape_bg(slide, left, top, width, height, color):
    shape = slide.shapes.add_shape(1, Inches(left), Inches(top), Inches(width), Inches(height))  # MSO_SHAPE.RECTANGLE
    shape.fill.solid()
    shape.fill.fore_color.rgb = color
    shape.line.fill.background()
    return shape

# ========== 幻燈片內容 ==========
slides_data = [
    # Slide 1 - Title
    {"type": "title", "kicker": "Organization Management", "title": "組織管理\n課程導論", "subtitle": "課程說明、評分方式、組織管理的重要性、基本概念與管理者角色"},
    # Slide 2 - Executive Summary
    {"type": "grid4", "kicker": "Executive Summary", "title": "本課程重點", 
     "items": [("看懂組織", "掌握組織如何分工、協調與達成共同目標。"), ("理解管理", "學習規劃、組織、領導與控制的完整循環。"), ("辨識角色", "分析管理者在不同情境下的多重職責。"), ("應用案例", "用討論、報告與反思連結真實管理問題。")]},
    # Slide 3 - Course Logic
    {"type": "split", "kicker": "Course Logic", "title": "課程定位",
     "left": "從人到系統\n\n組織管理不是只談個人效率，而是理解群體如何透過制度、文化與決策創造績效。\n\n本課程強調概念理解、案例判讀與管理思維。", "left_color": NAVY},
    # Slide 4 - Learning Goals
    {"type": "bullet", "kicker": "Learning Goals", "title": "學習目標",
     "items": ["說明組織存在的目的與基本構成。", "辨識管理活動在不同層級的差異。", "運用概念分析組織設計與管理情境。", "建立能支持團隊合作與決策的管理語言。"]},
    # Slide 5 - 18 Weeks Map
    {"type": "timeline", "kicker": "18 Weeks Map", "title": "十八週架構",
     "items": [("01", "導論", "課程說明、評分、組織管理重要性。"), ("02", "概念", "組織、管理、管理者與環境。"), ("03", "職能", "規劃、組織、領導與控制。"), ("04", "議題", "文化、溝通、激勵、團隊與變革。"), ("05", "整合", "案例分析、期末報告與反思。")]},
    # Slide 6 - Assessment
    {"type": "bars", "kicker": "Assessment", "title": "評分方式",
     "items": [("課堂參與", 20), ("平時作業", 25), ("小組報告", 25), ("期末評量", 30)]},
    # Slide 7 - Evaluation Design
    {"type": "metrics", "kicker": "Evaluation Design", "title": "評量邏輯",
     "items": [("40%", "理解", "掌握核心理論與管理語言。"), ("35%", "應用", "把概念放進案例與問題脈絡。"), ("25%", "表達", "清楚呈現觀點、證據與建議。")]},
    # Slide 8 - Participation
    {"type": "grid3", "kicker": "Participation", "title": "課堂參與",
     "items": [("準備", "課前閱讀，帶著問題進教室。"), ("發言", "提出觀察、反例或不同解釋。"), ("協作", "尊重差異，讓討論形成共同成果。")]},
    # Slide 9 - Assignments
    {"type": "split", "kicker": "Assignments", "title": "平時作業",
     "left": "作業不是摘要\n\n重點在於用課程概念解釋一個管理現象，並說明你的判斷依據。", "left_color": NAVY,
     "right": "建議格式\n\n情境描述 → 概念選擇 → 分析推論 → 管理建議。", "right_color": BG},
    # Slide 10 - Team Project
    {"type": "split", "kicker": "Team Project", "title": "小組報告",
     "left": "核心任務\n\n選擇一個組織管理問題，提出診斷、分析與可執行建議。\n\n重點不是描述公司，而是說清楚管理問題如何形成。", "left_color": NAVY},
    # Slide 11 - Final Evaluation
    {"type": "grid3", "kicker": "Final Evaluation", "title": "期末評量",
     "items": [("概念題", "檢視定義、比較與關鍵差異。"), ("案例題", "以理論診斷情境中的管理問題。"), ("應用題", "提出合理、可落地的管理建議。")]},
    # Slide 12 - Class Norms
    {"type": "bullet", "kicker": "Class Norms", "title": "課堂規範",
     "items": ["準時出席，缺席需依課程規定處理。", "引用資料需標明來源，避免不當使用。", "小組合作需清楚分工並保留討論紀錄。", "課堂討論重視邏輯、證據與尊重。"]},
    # Slide 13 - Why It Matters
    {"type": "quote", "kicker": "Why It Matters", "title": "組織管理價值",
     "quote": "個人的努力創造表現；\n組織的設計決定表現能否被放大。"},
    # Slide 14 - Organization
    {"type": "grid3", "kicker": "Organization", "title": "何謂組織",
     "items": [("共同目標", "成員被某個目的連結，並願意投入行動。"), ("分工結構", "任務被拆解並配置責任，形成可運作的系統。"), ("協調機制", "透過制度與溝通整合行動，降低內部摩擦。")]},
    # Slide 15 - Management
    {"type": "split", "kicker": "Management", "title": "何謂管理",
     "left": "透過他人完成事情\n\n管理是協調資源、設定方向、帶動行動並檢視成果的持續過程。\n\n它同時處理目標、資源、人員與績效。", "left_color": NAVY},
    # Slide 16 - Core Distinction
    {"type": "split2", "kicker": "Core Distinction", "title": "組織與管理",
     "left": "組織\n\n回答「人與任務如何被安排」。重點是結構、分工與協調。", "right": "管理\n\n回答「如何讓安排產生結果」。重點是決策、行動與修正。"},
    # Slide 17 - Analysis Lens
    {"type": "grid4", "kicker": "Analysis Lens", "title": "分析層次",
     "items": [("個人", "能力、動機、態度。"), ("團隊", "互動、衝突、合作。"), ("組織", "結構、流程、文化。"), ("環境", "市場、技術、制度。")]},
    # Slide 18 - Environment
    {"type": "grid3", "kicker": "Environment", "title": "外部環境",
     "items": [("變動", "需求、政策與技術持續改變。"), ("限制", "資源稀缺，選擇必須取捨。"), ("機會", "新情境也創造新的組織可能。")]},
    # Slide 19 - Structure
    {"type": "grid3", "kicker": "Structure", "title": "內部結構",
     "items": [("部門化", "依功能、產品、地區或客群配置工作。"), ("層級化", "界定權責、回報與決策路徑。"), ("標準化", "用流程與規範降低不確定性。")]},
    # Slide 20 - Formal vs Informal
    {"type": "split2", "kicker": "Formal vs Informal", "title": "正式與非正式",
     "left": "正式組織\n\n制度、職位、流程與明確權責，讓行動有穩定基礎。", "right": "非正式組織\n\n人際網絡、信任、習慣與潛規則，影響實際運作。"},
    # Slide 21 - Goal Alignment
    {"type": "metrics", "kicker": "Goal Alignment", "title": "目標與績效",
     "items": [("1", "方向", "目標讓成員知道要往哪裡走。"), ("2", "衡量", "績效指標讓成果可以被檢視。"), ("3", "校正", "回饋讓組織能調整行動。")]},
    # Slide 22 - Division of Labor
    {"type": "split2", "kicker": "Division of Labor", "title": "分工與專業化",
     "left": "效率來源\n\n分工能提升熟練度、縮短學習曲線，並讓責任更清楚。", "right": "管理挑戰\n\n分工越細，越需要跨部門協調、資訊共享與共同目標。"},
    # Slide 23 - Coordination
    {"type": "timeline", "kicker": "Coordination", "title": "協調機制",
     "items": [("A", "規則", "用制度處理重複問題。"), ("B", "會議", "用討論整合跨域資訊。"), ("C", "流程", "用節點管理任務交接。"), ("D", "文化", "用共同價值降低摩擦。"), ("E", "科技", "用工具提升透明與速度。")]},
    # Slide 24 - Authority
    {"type": "grid3", "kicker": "Authority", "title": "權責關係",
     "items": [("權力", "影響他人行動的能力。"), ("責任", "對任務結果承擔回應義務。"), ("授權", "讓決策更接近資訊與現場。")]},
    # Slide 25 - Culture
    {"type": "split", "kicker": "Culture", "title": "文化與價值",
     "left": "文化是隱形規則\n\n它決定什麼行為被鼓勵、被忽略，或被視為不合理。\n\n文化不只是口號，而是日常選擇的累積。", "left_color": NAVY},
    # Slide 26 - Functions
    {"type": "grid4", "kicker": "Functions", "title": "管理四職能",
     "items": [("規劃", "決定方向與目標。"), ("組織", "配置資源與任務。"), ("領導", "影響人與凝聚行動。"), ("控制", "檢視結果並修正。")]},
    # Slide 27 - Planning
    {"type": "grid3", "kicker": "Planning", "title": "規劃職能",
     "items": [("設定目標", "將抽象願景轉成可追蹤成果。"), ("選擇策略", "在限制條件下決定優先順序。"), ("配置資源", "把時間、人力與預算放在關鍵處。")]},
    # Slide 28 - Organizing
    {"type": "grid3", "kicker": "Organizing", "title": "組織職能",
     "items": [("任務設計", "把大目標拆成清楚工作。"), ("權責配置", "讓每個角色知道能做什麼。"), ("流程整合", "確保不同單位能順利銜接。")]},
    # Slide 29 - Leading
    {"type": "split2", "kicker": "Leading", "title": "領導職能",
     "left": "影響而非命令\n\n領導的關鍵在於建立意義、信任與行動意願。", "right": "三個核心\n\n溝通方向、激勵投入、處理衝突，讓團隊願意一起前進。"},
    # Slide 30 - Controlling
    {"type": "timeline", "kicker": "Controlling", "title": "控制職能",
     "items": [("1", "設定標準", "先定義何謂好表現。"), ("2", "衡量現況", "收集可靠資訊。"), ("3", "比較差距", "找出偏差來源。"), ("4", "採取修正", "調整流程或資源。"), ("5", "形成學習", "讓制度持續改善。")]},
    # Slide 31 - Decision Making
    {"type": "grid3", "kicker": "Decision Making", "title": "決策基礎",
     "items": [("問題界定", "問對問題，比立刻找答案更重要。"), ("方案比較", "用標準衡量選項的利弊。"), ("執行追蹤", "決策價值取決於落地效果。")]},
    # Slide 32 - Managerial Levels
    {"type": "grid3", "kicker": "Managerial Levels", "title": "管理層級",
     "items": [("高階管理者", "設定方向，處理策略與外部關係。"), ("中階管理者", "轉譯策略，整合部門與專案。"), ("基層管理者", "管理現場，確保任務與品質。")]},
    # Slide 33 - Manager Roles
    {"type": "metrics", "kicker": "Manager Roles", "title": "管理者角色",
     "items": [("I", "人際角色", "代表、領導與聯絡。"), ("II", "資訊角色", "監聽、傳播與發言。"), ("III", "決策角色", "創業、處理干擾、配置資源。")]},
    # Slide 34 - Interpersonal
    {"type": "grid3", "kicker": "Interpersonal", "title": "人際角色",
     "items": [("代表者", "在正式場合象徵組織。"), ("領導者", "引導部屬完成任務。"), ("聯絡者", "建立跨部門與外部網絡。")]},
    # Slide 35 - Informational
    {"type": "grid3", "kicker": "Informational", "title": "資訊角色",
     "items": [("監聽者", "蒐集組織內外的關鍵訊息。"), ("傳播者", "把資訊轉換成團隊可用的理解。"), ("發言人", "向外部傳達組織立場與成果。")]},
    # Slide 36 - Decisional
    {"type": "grid4", "kicker": "Decisional", "title": "決策角色",
     "items": [("創業者", "推動改善與創新。"), ("排除干擾", "處理危機與衝突。"), ("資源配置", "決定資源投入順序。"), ("談判者", "協調利益與交換條件。")]},
    # Slide 37 - Managerial Skills
    {"type": "grid3", "kicker": "Managerial Skills", "title": "管理技能",
     "items": [("技術技能", "理解工作方法與專業工具。"), ("人際技能", "溝通、協調、激勵與衝突處理。"), ("概念技能", "看見系統關係與長期影響。")]},
    # Slide 38 - Case Method
    {"type": "timeline", "kicker": "Case Method", "title": "案例討論法",
     "items": [("1", "看見事實", "先分清資料與判斷。"), ("2", "界定問題", "找出真正管理痛點。"), ("3", "選擇概念", "用理論建立分析框架。"), ("4", "提出方案", "比較可行性與風險。"), ("5", "反思學習", "把案例轉成可遷移能力。")]},
    # Slide 39 - Learning Journey
    {"type": "bars", "kicker": "Learning Journey", "title": "學期學習線",
     "items": [("第 1–3 週", 18), ("第 4–7 週", 40), ("第 8–12 週", 68), ("第 13–16 週", 88), ("第 17–18 週", 100)]},
    # Slide 40 - Closing
    {"type": "closing", "kicker": "Closing", "title": "課程契約",
     "quote": "好的管理學習，始於願意問：\n為什麼這個組織會這樣運作？",
     "next": "帶著觀察進入課堂，帶著概念離開教室，帶著方法分析真實組織。\n\n本課程重視參與、思考與清楚表達。"},
]

for i, sd in enumerate(slides_data):
    slide = prs.slides.add_slide(prs.slide_layouts[6])  # blank layout
    add_bg(slide)
    
    # 添加裝飾色帶（頂部）
    ribbon = slide.shapes.add_shape(1, Inches(0), Inches(0), Inches(13.333), Inches(0.15))
    ribbon.fill.solid()
    ribbon.fill.fore_color.rgb = NAVY
    ribbon.line.fill.background()
    
    # 頁碼
    add_text(slide, 0.4, 7.0, 1.5, 0.4, f"{i+1:02d} / 40", 12, MUTED, False)
    
    # Kicker
    add_text(slide, 0.5, 0.4, 4, 0.4, sd.get("kicker", ""), 16, TEAL, True)
    
    t = sd.get("type", "")
    
    if t == "title":
        add_text(slide, 0.5, 1.0, 6, 1.5, sd["title"], 56, NAVY, True)
        add_text(slide, 0.5, 3.0, 6, 1.0, sd["subtitle"], 24, MUTED, False)
        
    elif t in ["grid3", "grid4"]:
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        cols = len(sd["items"])
        card_w = 3.8 if cols == 3 else 2.8
        gap = 0.4
        start_x = 0.5
        for j, (name, desc) in enumerate(sd["items"]):
            x = start_x + j * (card_w + gap)
            # Card background
            card = slide.shapes.add_shape(1, Inches(x), Inches(2.0), Inches(card_w), Inches(4.5))
            card.fill.solid()
            card.fill.fore_color.rgb = WHITE
            card.line.fill.background()
            # Card title
            add_text(slide, x + 0.3, 2.3, card_w - 0.6, 0.5, name, 28, NAVY, True)
            # Card desc
            add_text(slide, x + 0.3, 3.0, card_w - 0.6, 3.0, desc, 22, MUTED, False)
            
    elif t == "bullet":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        for j, item in enumerate(sd["items"]):
            y = 2.2 + j * 1.1
            # Bullet card
            card = slide.shapes.add_shape(1, Inches(0.5), Inches(y), Inches(12), Inches(0.9))
            card.fill.solid()
            card.fill.fore_color.rgb = WHITE
            card.line.fill.background()
            # Left border
            border = slide.shapes.add_shape(1, Inches(0.5), Inches(y), Inches(0.08), Inches(0.9))
            border.fill.solid()
            border.fill.fore_color.rgb = TEAL
            border.line.fill.background()
            add_text(slide, 0.8, y + 0.15, 11, 0.6, item, 24, NAVY, False)
            
    elif t == "timeline":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        cols = len(sd["items"])
        card_w = 2.2
        gap = 0.25
        start_x = 0.5
        for j, (num, name, desc) in enumerate(sd["items"]):
            x = start_x + j * (card_w + gap)
            card = slide.shapes.add_shape(1, Inches(x), Inches(2.0), Inches(card_w), Inches(4.5))
            card.fill.solid()
            card.fill.fore_color.rgb = WHITE
            card.line.fill.background()
            # Top border
            top_border = slide.shapes.add_shape(1, Inches(x), Inches(2.0), Inches(card_w), Inches(0.12))
            top_border.fill.solid()
            top_border.fill.fore_color.rgb = TEAL
            top_border.line.fill.background()
            # Number
            add_text(slide, x + 0.2, 2.3, card_w - 0.4, 0.6, num, 36, GOLD, True)
            # Name
            add_text(slide, x + 0.2, 3.0, card_w - 0.4, 0.5, name, 22, NAVY, True)
            # Desc
            add_text(slide, x + 0.2, 3.7, card_w - 0.4, 2.5, desc, 18, MUTED, False)
            
    elif t == "bars":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        for j, (name, pct) in enumerate(sd["items"]):
            y = 2.2 + j * 1.1
            add_text(slide, 0.5, y, 2.5, 0.5, name, 24, NAVY, True)
            # Track
            track = slide.shapes.add_shape(1, Inches(3.2), Inches(y + 0.1), Inches(7.5), Inches(0.35))
            track.fill.solid()
            track.fill.fore_color.rgb = RGBColor(220, 220, 230)
            track.line.fill.background()
            # Fill
            fill_w = 7.5 * pct / 100
            fill = slide.shapes.add_shape(1, Inches(3.2), Inches(y + 0.1), Inches(fill_w), Inches(0.35))
            fill.fill.solid()
            fill.fill.fore_color.rgb = TEAL
            fill.line.fill.background()
            add_text(slide, 11.0, y, 1.5, 0.5, f"{pct}%", 22, NAVY, True)
            
    elif t == "metrics":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        cols = len(sd["items"])
        card_w = 3.8
        gap = 0.4
        start_x = 0.5
        for j, (metric, name, desc) in enumerate(sd["items"]):
            x = start_x + j * (card_w + gap)
            card = slide.shapes.add_shape(1, Inches(x), Inches(2.0), Inches(card_w), Inches(4.5))
            card.fill.solid()
            card.fill.fore_color.rgb = WHITE
            card.line.fill.background()
            add_text(slide, x + 0.3, 2.3, card_w - 0.6, 0.8, metric, 56, GOLD, True)
            add_text(slide, x + 0.3, 3.3, card_w - 0.6, 0.5, name, 28, NAVY, True)
            add_text(slide, x + 0.3, 4.0, card_w - 0.6, 2.0, desc, 22, MUTED, False)
            
    elif t == "split":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        # Left card (dark)
        left_card = slide.shapes.add_shape(1, Inches(0.5), Inches(2.0), Inches(6.0), Inches(4.8))
        left_card.fill.solid()
        left_card.fill.fore_color.rgb = sd.get("left_color", NAVY)
        left_card.line.fill.background()
        add_text(slide, 1.0, 2.5, 5.0, 4.0, sd["left"], 24, WHITE, False)
        # Right photo frame
        right_frame = slide.shapes.add_shape(1, Inches(6.8), Inches(2.0), Inches(6.0), Inches(4.8))
        right_frame.fill.solid()
        right_frame.fill.fore_color.rgb = RGBColor(200, 210, 215)
        right_frame.line.fill.background()
        add_text(slide, 7.3, 3.5, 5.0, 2.0, "📷 圖片區", 20, MUTED, False)
        
    elif t == "split2":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["title"], 44, NAVY, True)
        # Left
        left_card = slide.shapes.add_shape(1, Inches(0.5), Inches(2.0), Inches(5.8), Inches(4.8))
        left_card.fill.solid()
        left_card.fill.fore_color.rgb = NAVY
        left_card.line.fill.background()
        add_text(slide, 1.0, 2.5, 4.8, 4.0, sd["left"], 24, WHITE, False)
        # Right
        right_card = slide.shapes.add_shape(1, Inches(6.8), Inches(2.0), Inches(6.0), Inches(4.8))
        right_card.fill.solid()
        right_card.fill.fore_color.rgb = WHITE
        right_card.line.fill.background()
        add_text(slide, 7.3, 2.5, 5.0, 4.0, sd["right"], 24, NAVY, False)
        
    elif t == "quote":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["kicker"], 16, TEAL, True)
        add_text(slide, 0.5, 1.5, 12, 0.8, sd["title"], 44, NAVY, True)
        # Quote card
        quote_card = slide.shapes.add_shape(1, Inches(1.5), Inches(2.5), Inches(10.3), Inches(4.0))
        quote_card.fill.solid()
        quote_card.fill.fore_color.rgb = NAVY
        quote_card.line.fill.background()
        add_text(slide, 2.5, 3.2, 8.3, 2.8, sd["quote"], 36, WHITE, True, PP_ALIGN.CENTER)
        
    elif t == "closing":
        add_text(slide, 0.5, 1.0, 12, 0.8, sd["kicker"], 16, TEAL, True)
        add_text(slide, 0.5, 1.5, 12, 0.8, sd["title"], 44, NAVY, True)
        # Quote
        quote_card = slide.shapes.add_shape(1, Inches(0.5), Inches(2.5), Inches(6.5), Inches(4.0))
        quote_card.fill.solid()
        quote_card.fill.fore_color.rgb = NAVY
        quote_card.line.fill.background()
        add_text(slide, 1.0, 3.0, 5.5, 3.0, sd["quote"], 32, WHITE, True, PP_ALIGN.CENTER)
        # Next steps
        next_card = slide.shapes.add_shape(1, Inches(7.3), Inches(2.5), Inches(5.5), Inches(4.0))
        next_card.fill.solid()
        next_card.fill.fore_color.rgb = WHITE
        next_card.line.fill.background()
        add_text(slide, 7.8, 2.8, 4.5, 0.5, "下一步", 28, NAVY, True)
        add_text(slide, 7.8, 3.5, 4.5, 2.5, sd["next"], 20, MUTED, False)

prs.save('/Users/lingochen/Desktop/組織管理課程說明簡報.pptx')
print('✅ PPT 已完成！共 {} 頁'.format(len(slides_data)))
