# 프로젝트 경로 유틸리티 — 개발/EXE 환경 모두에서 상대↔절대 경로 일관 처리
#
# 두 종류의 루트가 있음:
#   PROJECT_ROOT : 사용자가 보는 실제 폴더. 로그/설정/모델 등 쓰기 가능한 위치.
#                  - dev 모드: 이 파일이 있는 폴더 (E:\ANT)
#                  - EXE(--onefile) 모드: EXE가 놓인 폴더 (예: E:\ANT\dist)
#   BUNDLE_ROOT  : 번들에 포함된 읽기 전용 자원 위치.
#                  - dev 모드: PROJECT_ROOT 와 동일
#                  - EXE 모드: PyInstaller 임시 추출 폴더 (sys._MEIPASS)
import os
import sys

_FROZEN = getattr(sys, "frozen", False)

# 번들된 자원(읽기 전용): config.json, ai/models, assets 등
BUNDLE_ROOT = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))

# 사용자 데이터(읽기/쓰기): logs, 변경된 config, 새로 저장된 모델 등
if _FROZEN:
    PROJECT_ROOT = os.path.dirname(os.path.abspath(sys.executable))
else:
    PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))


def resolve_path(path: str) -> str:
    """상대경로 → 절대경로 변환.
    1) 절대경로/빈 값은 그대로 반환
    2) PROJECT_ROOT 기준 경로가 존재하면 사용 (사용자가 변경한 사본 우선)
    3) BUNDLE_ROOT 기준 경로가 존재하면 폴백 (번들 기본 사본)
    4) 둘 다 없으면 PROJECT_ROOT 기준 경로 반환 (신규 생성 시 사용자 영역에 만들도록)
    """
    if not path:
        return path
    if os.path.isabs(path):
        return os.path.normpath(path)
    primary = os.path.normpath(os.path.join(PROJECT_ROOT, path))
    if os.path.exists(primary):
        return primary
    if BUNDLE_ROOT and BUNDLE_ROOT != PROJECT_ROOT:
        fallback = os.path.normpath(os.path.join(BUNDLE_ROOT, path))
        if os.path.exists(fallback):
            return fallback
    return primary


def to_project_relative(path: str) -> str:
    """PROJECT_ROOT 또는 BUNDLE_ROOT 하위면 슬래시 구분 상대경로로, 외부면 슬래시 구분 절대경로로."""
    if not path:
        return path
    abs_path = os.path.abspath(path)
    for root in (PROJECT_ROOT, BUNDLE_ROOT):
        if not root:
            continue
        try:
            rel = os.path.relpath(abs_path, root)
        except ValueError:
            continue
        if not rel.startswith(".."):
            return rel.replace("\\", "/")
    return abs_path.replace("\\", "/")
