# upgraded: inherit base class
# utils/path_utils.py
import logging
import os
import shutil
import sys
from pathlib import Path

LOGGER = logging.getLogger(__name__)
_RES_BOOTSTRAPPED = False
# edited by glg
# Hindari spam warning fallback db_path dan lakukan auto-heal config sekali per proses.
_DB_PATH_FALLBACK_WARNED = False
_DB_PATH_AUTOFIX_ATTEMPTED = False


def get_app_resource_dir():
    meipass = getattr(sys, "_MEIPASS", None)
    if meipass:
        return os.path.abspath(meipass)

    install_base = get_install_base_dir()
    if os.path.isdir(os.path.join(install_base, "pypos")):
        return install_base

    return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", ".."))


def get_project_base_dir():
    return get_app_resource_dir()


def get_install_base_dir():
    return os.path.abspath(os.path.dirname(sys.argv[0]))


def get_app_data_dir():
    appdata = os.environ.get("APPDATA") or os.environ.get("LOCALAPPDATA")
    if not appdata:
        appdata = os.path.join(os.path.expanduser("~"), ".config")
    path = os.path.join(appdata, "PyPOS")
    os.makedirs(path, exist_ok=True)
    return path


def _copy_missing_tree(src: str, dst: str):
    src_path = Path(src)
    dst_path = Path(dst)
    if not src_path.exists():
        return
    for item in src_path.rglob("*"):
        if "__pycache__" in item.parts:
            continue
        rel = item.relative_to(src_path)
        target = dst_path / rel
        if item.is_dir():
            target.mkdir(parents=True, exist_ok=True)
            continue
        target.parent.mkdir(parents=True, exist_ok=True)
        if not target.exists():
            shutil.copy2(item, target)


def _copy_default_if_missing(target: str, candidates):
    if os.path.exists(target):
        return True
    os.makedirs(os.path.dirname(target), exist_ok=True)
    for src in candidates:
        if src and os.path.exists(src):
            shutil.copy2(src, target)
            return True
    return False


def _is_subpath(path: str, base_dir: str):
    try:
        path_abs = os.path.abspath(path)
        base_abs = os.path.abspath(base_dir)
        return os.path.commonpath([path_abs, base_abs]) == base_abs
    except (OSError, ValueError):
        return False


def _seed_runtime_resources():
    global _RES_BOOTSTRAPPED
    if _RES_BOOTSTRAPPED:
        return

    user_res = os.path.join(get_app_data_dir(), "resources")
    os.makedirs(user_res, exist_ok=True)

    install_base = get_install_base_dir()
    bundle_base = get_app_resource_dir()
    candidates = [
        os.path.join(install_base, "pypos", "assets"),
        os.path.join(bundle_base, "pypos", "assets"),
        os.path.join(install_base, "resources"),
        os.path.join(bundle_base, "resources"),
    ]
    for src in candidates:
        _copy_missing_tree(src, user_res)
    _RES_BOOTSTRAPPED = True


def get_app_data_resource_dir():
    _seed_runtime_resources()
    return os.path.join(get_app_data_dir(), "resources")


def get_assets_path():
    return get_app_data_resource_dir()


def get_resources_path():
    return get_app_data_resource_dir()


def get_db_path():
    global _DB_PATH_FALLBACK_WARNED, _DB_PATH_AUTOFIX_ATTEMPTED
    app_data = get_app_data_dir()
    app_data_default_db = os.path.join(app_data, "db", "beta_sb_pos_sqlite.db")
    cfg_path = None
    try:
        from pypos.core.utils.config_utils import read_app_settings, save_app_settings
        cfg_path = (read_app_settings() or {}).get("db_path")
    except (ImportError, ModuleNotFoundError, OSError, ValueError, TypeError) as e:
        LOGGER.warning("Gagal baca db_path via config layer: %s", e)
        save_app_settings = None
    if cfg_path:
        db_path = cfg_path if os.path.isabs(cfg_path) else os.path.join(app_data, cfg_path)
    else:
        db_path = app_data_default_db

    install_base = get_install_base_dir()
    bundle_base = get_app_resource_dir()

    if _is_subpath(db_path, install_base) or _is_subpath(db_path, bundle_base):
        if not _DB_PATH_FALLBACK_WARNED:
            LOGGER.warning(
                "db_path mengarah ke direktori install/bundle. Fallback ke APPDATA. path=%s",
                db_path,
            )
            _DB_PATH_FALLBACK_WARNED = True
        # edited by glg
        # Auto-heal agar warning tidak berulang pada run berikutnya.
        if not _DB_PATH_AUTOFIX_ATTEMPTED and save_app_settings is not None:
            _DB_PATH_AUTOFIX_ATTEMPTED = True
            try:
                save_app_settings({"db_path": os.path.join("db", "beta_sb_pos_sqlite.db")})
                LOGGER.info("Auto-heal db_path ke APPDATA-relative berhasil.")
            except (OSError, RuntimeError, ValueError, TypeError) as e:
                LOGGER.warning("Auto-heal db_path gagal: %s", e)
        db_path = app_data_default_db

    rel_default = os.path.join("db", "beta_sb_pos_sqlite.db")
    source_candidates = [
        os.path.join(install_base, rel_default),
        os.path.join(bundle_base, rel_default),
        os.path.join(install_base, "db", "beta_sb_pos_sqlite_.db"),
        os.path.join(bundle_base, "db", "beta_sb_pos_sqlite_.db"),
    ]
    copied = _copy_default_if_missing(db_path, source_candidates)
    if not copied:
        raise RuntimeError(
            "Template database tidak ditemukan. Pastikan file db/beta_sb_pos_sqlite.db tersedia di bundle atau instalasi."
        )
    return db_path
