# -*- mode: python ; coding: utf-8 -*-
"""S-CANVAS PyInstaller spec — onedir 배포 빌드 설정.

빌드:
    pyinstaller --clean scanvas_maker.spec

결과:
    dist/S-CANVAS/                   ← 통째로 zip 해서 배포
        S-CANVAS.exe                 ← 더블클릭 진입점
        Design/, prompt_templates/, structure_types/
        _internal/                   ← Python 런타임 + 의존 라이브러리
        ...

런타임 데이터(DB·로그·캐시):
    %LOCALAPPDATA%\\S-CANVAS\\        ← 사용자별 분리, 설치 폴더 쓰기 권한 불필요
"""
from PyInstaller.utils.hooks import collect_all, collect_submodules
from pathlib import Path

block_cipher = None
PROJECT_DIR = Path(SPECPATH).resolve()


# ────────────────────── 자산 번들링 ──────────────────────
# (소스경로, 번들 내 상대경로) — 런타임에서 sys._MEIPASS 아래에 같은 트리로 추출됨.
datas = [
    (str(PROJECT_DIR / "Design"), "Design"),
    (str(PROJECT_DIR / "prompt_templates"), "prompt_templates"),
    (str(PROJECT_DIR / "structure_types"), "structure_types"),
]

# ────────────────────── 거대 패키지 collect_all ──────────────────────
# pyvista/vtk: PyInstaller 자동 감지 부분이 거나 → 명시적 collect_all 로 누락 방지.
# pyproj: PROJ 데이터(proj.db) 자동 누락 빈번 → collect_all 로 datas/binaries 모두 집어 옴.
binaries = []
hiddenimports = []
for pkg in [
    "pyvista",
    "vtkmodules",
    "pyproj",
    "ezdxf",
    "tkintermapview",
    "structlog",
    "customtkinter",
    "PIL",
]:
    try:
        _d, _b, _h = collect_all(pkg)
        datas += _d
        binaries += _b
        hiddenimports += _h
    except Exception:
        pass

# google-genai 의 서브모듈은 collect_all 로 충분히 커버되지 않을 때가 있어 별도 추가
hiddenimports += collect_submodules("google.genai")
hiddenimports += [
    "sqlalchemy.dialects.sqlite",
    "sqlalchemy.dialects.sqlite.pysqlite",
    "sqlalchemy.ext.declarative",
    "scipy.spatial.transform._rotation_groups",
    "scipy.special.cython_special",
    "encodings.idna",
]

# ────────────────────── 분석 단계 ──────────────────────
a = Analysis(
    ["scanvas_maker.py"],
    pathex=[str(PROJECT_DIR)],
    binaries=binaries,
    datas=datas,
    hiddenimports=hiddenimports,
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    # 번들 크기 절감: 불필요한 거대 패키지 제외
    excludes=[
        "pytest",
        "IPython",
        "jupyter",
        "notebook",
        "tornado",
        "zmq",
        "matplotlib.tests",
        "numpy.tests",
        "scipy.tests",
        "pyvista.examples",  # 거대 샘플 데이터 제외
        "vtkmodules.test",
    ],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

# ────────────────────── 실행파일 ──────────────────────
# 아이콘: 빌드 전 build.bat 가 cache/icons/scanvas_S.ico 를 생성. 없으면 None 폴백.
_icon_path = PROJECT_DIR / "cache" / "icons" / "scanvas_S.ico"
_exe_icon = str(_icon_path) if _icon_path.exists() else None

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name="S-CANVAS",
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,            # UPX 가 PATH 에 있으면 압축. 없어도 빌드 진행.
    upx_exclude=[
        "vcruntime140.dll",
        "python311.dll",
        "python312.dll",
        "VCRUNTIME140.dll",
    ],
    console=False,        # GUI 앱 — 콘솔 창 안 띄움
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=_exe_icon,
)

# ────────────────────── onedir 패키지 ──────────────────────
coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name="S-CANVAS",
)
