#!/usr/bin/env python3
"""
AI Platform 메뉴 안내 PPT — 일반 임직원(관리자·특수 메뉴 제외)
- 가이드봇·WM·대시보드·업무 체크리스트: 허용 계정만 (본 PPT 범위 외)
"""
from __future__ import annotations

from pathlib import Path

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

ROOT = Path(__file__).resolve().parent.parent
SHOT_DIR = ROOT / "docs" / "ppt-screenshots-user"
OUT_PPT = ROOT / "docs" / "XAVIS-AI-Platform-메뉴안내-일반사용자.pptx"

# Brand palette
NAVY = RGBColor(0x0F, 0x17, 0x2A)
BLUE = RGBColor(0x25, 0x63, 0xEB)
BLUE_LIGHT = RGBColor(0xDB, 0xEA, 0xFE)
SLATE = RGBColor(0x47, 0x55, 0x69)
SLATE_LIGHT = RGBColor(0x94, 0xA3, 0xB8)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
BG = RGBColor(0xF8, 0xFA, 0xFC)

SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)

SLIDES: list[tuple[str, str, list[str], str | None]] = [
    (
        "cover",
        "XAVIS AI Platform",
        [
            "일반 사용자 이용 가이드",
            "https://ai.xavis.co.kr/",
            "@ncue.net 이메일 인증 후 이용 · 관리자 모드 불필요",
        ],
        None,
    ),
    (
        "section",
        "시작하기",
        [],
        None,
    ),
    (
        "content",
        "이메일 인증으로 접속",
        [
            "1. ai.xavis.co.kr 접속 → 회사 이메일 입력 → [검증]",
            "2. 메일함 [인증 완료하기] 클릭 (링크 15분 유효)",
            "3. 인증 완료 후 AI·학습센터 등 메뉴 이용",
            "로그아웃: 좌측 하단 · 좌측 [관리자]는 운영 담당용(일반 사용자 불필요)",
        ],
        "login.png",
    ),
    (
        "content",
        "일반 사용자 메뉴 구성",
        [
            "AI — 회의록·채팅·FSCAN 등 AI 서비스",
            "프롬프트 — 업무용 템플릿·팀 공유",
            "학습센터 — YouTube·PPT·동영상 강의",
            "과제신청 — AX 과제 온라인 신청",
            "AI 활용 사례 — 임직원 간 실무 AI 활용 노하우 공유·열람",
            "※ 가이드봇·WM·대시보드·업무 체크리스트는 허용 계정만 표시",
        ],
        "menu-overview.png",
    ),
    (
        "section",
        "AI 서비스",
        [],
        None,
    ),
    (
        "content",
        "AI — 서비스 허브",
        [
            "경로: /ai-explore",
            "검색 + 타입 필터(전체 / 일반 / XScan / FScan)",
            "카드 클릭으로 각 AI 도구 실행",
        ],
        "ai-explore.png",
    ),
    (
        "content",
        "회의록 AI",
        [
            "텍스트: 회의 원문 붙여넣기 → [회의록 생성] → 수정 후 [저장]",
            "음성: mp3·m4a·wav(최대 300MB) → 업로드 → 전사 → 회의록 정리",
            "대안: 클로버노트·Claude 전사 → 텍스트 입력 탭에 붙여넣기",
            "유의: 결과 검토 필수 · 개인정보·대외비 주의",
        ],
        "meeting-minutes.png",
    ),
    (
        "content",
        "일반 채팅",
        [
            "이메일 인증 후 ChatGPT 기반 사내 채팅",
            "업무 질의·초안·아이디어 · (설정 시) 웹 검색",
            "반복 업무는 [프롬프트] 템플릿 복사 후 활용",
        ],
        "chat.png",
    ),
    (
        "content",
        "FSCAN 조사각 선정도우미",
        [
            "검사물 H/W 치수 입력 → FSCAN 모델 1차 선정",
            "영업·기술 검토용 · 최종 스펙은 공식 카탈로그·기술팀 확인",
        ],
        "fscan.png",
    ),
    (
        "section",
        "업무 지원",
        [],
        None,
    ),
    (
        "content",
        "프롬프트 라이브러리",
        [
            "공식 템플릿(회의·메일·보고·OKR 등) 미리보기 → 복사",
            "워크플로: 4단계 입력으로 맞춤 지시문 초안",
            "공유하기: 팀 프롬프트 등록(로그인 필요, 기밀 제외)",
        ],
        "prompts.png",
    ),
    (
        "content",
        "학습센터",
        [
            "YouTube · PPT/PDF · 동영상 · 웹 링크 강의 검색·시청",
            "카테고리: AX 사고 전환 · AI 툴 활용 · AI Agent · 바이브 코딩",
            "캡처: 등록 강의 목록 전체(무한 스크롤 로드 후)",
            "강의 등록·수정은 운영 담당 — 일반 사용자는 시청·검색",
        ],
        "learning.png",
    ),
    (
        "content",
        "AX 과제 신청",
        [
            "Word 양식 다운로드 + 온라인 신청서 작성",
            "본인 신청 조회·수정(부서·이름·이메일)",
            "유사 사례는 AI 활용 사례 메뉴 참고",
        ],
        "ax-apply.png",
    ),
    (
        "content",
        "AI 활용 사례 — 공유 공간과 열람",
        [
            "각자의 실무 AI 활용법을 전사 임직원과 공유하는 공간(학습센터=교육, 여기=현장 검증 사례)",
            "로그인 임직원 누구나 열람·글쓰기 · 부서·태그·검색으로 유사 사례 탐색",
            "AX 과제·새 업무 전 참고 · 카드 클릭 → STAR 상세·재현 방법 확인",
            "경로: 좌측 [AI 활용 사례] · Before/After·활용 도구·성과 중심",
        ],
        "ai-cases.png",
    ),
    (
        "content",
        "AI 활용 사례 — 나의 경험 공유하기",
        [
            "[글쓰기] → STAR 본문(배경→과제→AI 활용→성과) · 활용 AI 태그 · 썸네일",
            "동료가 내일 바로 따라 할 수 있도록 도구·절차·수치를 구체적으로(과장 금지)",
            "※ 개인정보·고객·기밀 미포함 · AI 결과는 본인 검증 후 · 문의 AI혁신팀",
        ],
        "ai-cases-compose.png",
    ),
    (
        "section",
        "정리",
        [],
        None,
    ),
    (
        "content",
        "업무별 Quick Reference",
        [
            "음성 회의록 → AI → 회의록 AI (또는 클로버노트 → 텍스트 입력)",
            "빠른 질문 → 일반 채팅 · 메일·보고 초안 → 프롬프트",
            "학습 → 학습센터 · AX 과제 → 과제신청 · 사례 → AI 활용 사례",
            "문의: AI혁신팀",
        ],
        None,
    ),
    (
        "closing",
        "감사합니다",
        [
            "XAVIS AI Platform",
            "https://ai.xavis.co.kr/",
            "AI혁신팀",
        ],
        None,
    ),
]


def _set_solid_fill(shape, color: RGBColor) -> None:
    shape.fill.solid()
    shape.fill.fore_color.rgb = color


def _add_header_bar(slide, title: str) -> None:
    bar = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0), SLIDE_W, Inches(0.95))
    _set_solid_fill(bar, NAVY)
    bar.line.fill.background()

    accent = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0.95), SLIDE_W, Inches(0.06))
    _set_solid_fill(accent, BLUE)
    accent.line.fill.background()

    tb = slide.shapes.add_textbox(Inches(0.55), Inches(0.18), Inches(10.5), Inches(0.55))
    tf = tb.text_frame
    tf.text = title
    p = tf.paragraphs[0]
    p.font.name = "Apple SD Gothic Neo"
    p.font.size = Pt(24)
    p.font.bold = True
    p.font.color.rgb = WHITE


def _add_footer(slide, page_num: int) -> None:
    line = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.55), Inches(7.05), Inches(12.2), Inches(0.015))
    _set_solid_fill(line, BLUE_LIGHT)
    line.line.fill.background()

    left = slide.shapes.add_textbox(Inches(0.55), Inches(7.12), Inches(5), Inches(0.28))
    ltf = left.text_frame
    ltf.text = "XAVIS AI Platform · 일반 사용자 가이드"
    lp = ltf.paragraphs[0]
    lp.font.size = Pt(9)
    lp.font.color.rgb = SLATE_LIGHT

    right = slide.shapes.add_textbox(Inches(11.8), Inches(7.12), Inches(1.0), Inches(0.28))
    rtf = right.text_frame
    rtf.text = str(page_num)
    rp = rtf.paragraphs[0]
    rp.font.size = Pt(9)
    rp.font.color.rgb = SLATE_LIGHT
    rp.alignment = PP_ALIGN.RIGHT


def _add_bullets(slide, bullets: list[str], left: float, top: float, width: float, height: float, font_size: int = 14) -> None:
    box = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
    tf = box.text_frame
    tf.word_wrap = True
    for i, line in enumerate(bullets):
        para = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        para.text = line
        para.font.name = "Apple SD Gothic Neo"
        para.font.size = Pt(font_size)
        para.font.color.rgb = SLATE
        para.space_after = Pt(8)
        para.level = 0
        if not line.startswith("※"):
            para.text = f"• {line}"


def _add_screenshot(slide, shot_name: str, left: float, top: float, width: float) -> bool:
    path = SHOT_DIR / shot_name
    if not path.is_file():
        return False
    pic = slide.shapes.add_picture(str(path), Inches(left), Inches(top), width=Inches(width))
    max_height = Inches(5.85)
    if pic.height > max_height:
        scale = max_height / pic.height
        pic.width = int(pic.width * scale)
        pic.height = int(pic.height * scale)
    frame = slide.shapes.add_shape(
        MSO_SHAPE.RECTANGLE,
        pic.left - Inches(0.04),
        pic.top - Inches(0.04),
        pic.width + Inches(0.08),
        pic.height + Inches(0.08),
    )
    frame.fill.background()
    frame.line.color.rgb = BLUE_LIGHT
    frame.line.width = Pt(1.25)
    # picture on top
    slide.shapes._spTree.remove(pic._element)
    slide.shapes._spTree.insert(-1, pic._element)
    return True


def add_cover_slide(prs: Presentation, title: str, bullets: list[str]) -> None:
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0), SLIDE_W, SLIDE_H)
    _set_solid_fill(bg, NAVY)
    bg.line.fill.background()

    stripe = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(2.8), SLIDE_W, Inches(0.08))
    _set_solid_fill(stripe, BLUE)
    stripe.line.fill.background()

    tb = slide.shapes.add_textbox(Inches(0.9), Inches(1.5), Inches(11.5), Inches(1.0))
    tf = tb.text_frame
    tf.text = title
    p = tf.paragraphs[0]
    p.font.size = Pt(44)
    p.font.bold = True
    p.font.color.rgb = WHITE

    sub = slide.shapes.add_textbox(Inches(0.9), Inches(3.2), Inches(11.0), Inches(2.5))
    stf = sub.text_frame
    for i, line in enumerate(bullets):
        para = stf.paragraphs[0] if i == 0 else stf.add_paragraph()
        para.text = line
        para.font.size = Pt(20 if i == 0 else 16)
        para.font.bold = i == 0
        para.font.color.rgb = BLUE_LIGHT if i == 0 else SLATE_LIGHT
        para.space_after = Pt(10)


def add_section_slide(prs: Presentation, title: str, page_num: int) -> None:
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0), SLIDE_W, SLIDE_H)
    _set_solid_fill(bg, BLUE)
    bg.line.fill.background()

    tb = slide.shapes.add_textbox(Inches(0.9), Inches(3.0), Inches(11), Inches(1.2))
    tf = tb.text_frame
    tf.text = title
    p = tf.paragraphs[0]
    p.font.size = Pt(36)
    p.font.bold = True
    p.font.color.rgb = WHITE
    _add_footer(slide, page_num)


def add_text_slide(prs: Presentation, title: str, bullets: list[str], page_num: int) -> None:
    """스크린샷 없이 본문만 — 설명·가이드용"""
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0.95), SLIDE_W, Inches(6.55))
    _set_solid_fill(bg, BG)
    bg.line.fill.background()

    _add_header_bar(slide, title)

    highlight = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.55), Inches(1.15), Inches(0.08), Inches(5.6))
    _set_solid_fill(highlight, BLUE)
    highlight.line.fill.background()

    _add_bullets(slide, bullets, 0.75, 1.25, 11.8, 5.5, font_size=15)
    _add_footer(slide, page_num)


def add_content_slide(prs: Presentation, title: str, bullets: list[str], shot_name: str | None, page_num: int) -> None:
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0.95), SLIDE_W, Inches(6.55))
    _set_solid_fill(bg, BG)
    bg.line.fill.background()

    _add_header_bar(slide, title)

    has_shot = shot_name and (SHOT_DIR / shot_name).is_file()
    text_w = 5.6 if has_shot else 12.0
    fs = 13 if len(bullets) >= 5 else 14
    _add_bullets(slide, bullets, 0.55, 1.25, text_w, 5.5, font_size=fs)

    if has_shot and shot_name:
        _add_screenshot(slide, shot_name, 6.45, 1.15, 6.35)

    _add_footer(slide, page_num)


def add_closing_slide(prs: Presentation, title: str, bullets: list[str], page_num: int) -> None:
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0), Inches(0), SLIDE_W, SLIDE_H)
    _set_solid_fill(bg, NAVY)
    bg.line.fill.background()

    tb = slide.shapes.add_textbox(Inches(0.9), Inches(2.6), Inches(11.5), Inches(1.0))
    tf = tb.text_frame
    tf.text = title
    p = tf.paragraphs[0]
    p.font.size = Pt(40)
    p.font.bold = True
    p.font.color.rgb = WHITE
    p.alignment = PP_ALIGN.CENTER

    sub = slide.shapes.add_textbox(Inches(0.9), Inches(3.8), Inches(11.5), Inches(1.5))
    stf = sub.text_frame
    for i, line in enumerate(bullets):
        para = stf.paragraphs[0] if i == 0 else stf.add_paragraph()
        para.text = line
        para.font.size = Pt(18)
        para.font.color.rgb = SLATE_LIGHT
        para.alignment = PP_ALIGN.CENTER
        para.space_after = Pt(6)

    _add_footer(slide, page_num)


def build() -> Path:
    prs = Presentation()
    prs.slide_width = SLIDE_W
    prs.slide_height = SLIDE_H

    page = 0
    for kind, title, bullets, shot in SLIDES:
        page += 1
        if kind == "cover":
            add_cover_slide(prs, title, bullets)
        elif kind == "section":
            add_section_slide(prs, title, page)
        elif kind == "closing":
            add_closing_slide(prs, title, bullets, page)
        elif kind == "text":
            add_text_slide(prs, title, bullets, page)
        else:
            add_content_slide(prs, title, bullets, shot, page)

    OUT_PPT.parent.mkdir(parents=True, exist_ok=True)
    prs.save(str(OUT_PPT))
    return OUT_PPT


if __name__ == "__main__":
    out = build()
    print(f"PPT saved: {out}")
