#!/usr/bin/env bash
# build-common.sh — shared functions for platform build scripts
# Source this file, do not execute directly.

# --- Version detection ---
# Fallback chain: CLI arg → git tag → CI env var → pyproject.toml
detect_version() {
    local arg="${1:-}"
    VERSION="${arg}"

    if [ -z "$VERSION" ]; then
        VERSION=$(git describe --tags --exact-match 2>/dev/null || true)
    fi

    if [ -z "$VERSION" ]; then
        VERSION="${GITEA_REF_NAME:-${GITHUB_REF_NAME:-}}"
    fi

    if [ -z "$VERSION" ]; then
        VERSION=$(grep -oP '^version\s*=\s*"\K[^"]+' \
          pyproject.toml 2>/dev/null || echo "0.0.0")
    fi

    VERSION_CLEAN="${VERSION#v}"

    # Normalize non-PEP440 labels (e.g. "dev", "nightly", "snapshot") to a
    # valid PEP440 dev release. Without this, pip/setuptools rejects
    # pyproject.toml with: `project.version` must be pep440.
    #
    # Valid forms:   1.2.3, 1.2.3a1, 1.2.3rc2, 1.2.3.dev0, 1.2.3.post1, +local
    # Invalid forms: dev, vdev, nightly, snapshot-2024
    if ! [[ "$VERSION_CLEAN" =~ ^[0-9]+(\.[0-9]+)*((a|b|rc|\.dev|\.post)[0-9]+)*(\+[a-zA-Z0-9.]+)?$ ]]; then
        echo "  Warning: '$VERSION_CLEAN' is not PEP440-compliant, using 0.0.0.dev0"
        VERSION_CLEAN="0.0.0.dev0"
    fi

    # Stamp version into pyproject.toml (single source of truth)
    sed -i "s/^version = .*/version = \"${VERSION_CLEAN}\"/" pyproject.toml
}

# --- Clean dist/build directories ---
clean_dist() {
    rm -rf dist build
    mkdir -p "$@"
}

# --- Verify frontend bundle exists ---
verify_frontend() {
    if [ ! -f "media_server/static/dist/app.bundle.js" ]; then
        echo "ERROR: Frontend bundle not found. Run 'npm ci && npm run build' first."
        exit 1
    fi
}

# --- Copy application files into dist ---
# Args: $1 = DIST_DIR
copy_app_files() {
    local dist_dir="$1"

    echo "Copying application files..."
    mkdir -p "${dist_dir}/app"
    cp -r media_server "${dist_dir}/app/"

    # Remove source JS (bundle is in dist/)
    rm -rf "${dist_dir}/app/media_server/static/js"
    # Remove source maps from release
    rm -f "${dist_dir}/app/media_server/static/dist/"*.map

    # Copy config example
    cp config.example.yaml "${dist_dir}/"

    # Write version file
    echo "$VERSION_CLEAN" > "${dist_dir}/VERSION"
}

# --- Clean up site-packages for smaller distribution ---
# Args: $1 = site-packages path, $2 = ext suffix (pyd|so), $3 = lib suffix (dll|so)
# Windows: cleanup_site_packages "$SP" "pyd" "dll"
# Linux:   cleanup_site_packages "$SP" "so"  "so"
cleanup_site_packages() {
    local sp_dir="$1"
    local ext_suffix="${2:-so}"
    local lib_suffix="${3:-so}"

    echo "Optimizing size..."

    # Generic cleanup
    find "$sp_dir" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
    find "$sp_dir" -type d -name tests -exec rm -rf {} + 2>/dev/null || true
    find "$sp_dir" -type d -name "*.dist-info" -exec rm -rf {} + 2>/dev/null || true
    find "$sp_dir" -name "*.pyi" -delete 2>/dev/null || true
    rm -rf "$sp_dir"/{pip,setuptools,pkg_resources,_distutils_hack}* 2>/dev/null || true

    # Trim numpy if present.
    # Keep only modules that numpy/__init__.py does NOT import unconditionally —
    # lib, linalg, ma, polynomial, fft, ctypeslib, matrixlib are all required for
    # `import numpy` to succeed, so they MUST stay.
    for mod in distutils f2py typing _pyinstaller; do
        rm -rf "$sp_dir/numpy/$mod" 2>/dev/null || true
    done

    # Trim OpenCV if present
    rm -f "$sp_dir"/cv2/opencv_videoio_ffmpeg*."$lib_suffix" 2>/dev/null || true
    rm -rf "$sp_dir"/cv2/{data,gapi,misc,utils,typing_stubs,typing} 2>/dev/null || true

    # Trim Pillow unused plugins if present
    rm -rf "$sp_dir"/PIL/{FpxImagePlugin,MicImagePlugin,McIdasImagePlugin}* 2>/dev/null || true

    # Trim zeroconf service DB if present
    rm -rf "$sp_dir"/zeroconf/_services 2>/dev/null || true

    # Strip debug symbols from native extensions
    find "$sp_dir" -name "*.$ext_suffix" -exec strip --strip-debug {} \; 2>/dev/null || true

    # NOTE: do NOT strip .py source files. A previous version of this function
    # ran `find ... -name "*.py" ! -name "__init__.py" -delete` with a comment
    # claiming "keep .pyc only" — but no compileall step exists, so the dist
    # shipped with __init__.py + .pyd only, missing every submodule (Image.py,
    # ImageDraw.py, _version.py, ...). Fresh installs would fail with
    # ModuleNotFoundError; in-place upgrades over an older install produced a
    # half-old/half-new site-packages where PIL/__init__.py was new but
    # PIL/_version.py was stale, yielding the runtime "_imaging extension was
    # built for another version of Pillow" import error.
}
