"""Map a Plex-side media path to Siftlode's local mount, so the player can open the physical file.

The Plex metadata gives each media Part an absolute path as the PLEX server sees it (e.g.
``/data/movies/Foo.mkv``). Siftlode plays the file directly, so it must translate that to the path
as SIFTLODE sees the same storage on a local mount (e.g. ``/plex-media/movies/Foo.mkv``). The map
is admin-configured (sysconfig ``plex_path_map``) as newline/comma-separated ``plexPrefix=localPrefix``
pairs; the longest matching Plex prefix wins. An empty map means the paths are identical on both
sides (Plex and Siftlode see the same filesystem).
"""
from pathlib import Path

from sqlalchemy.orm import Session

from app import sysconfig


def parse_map(raw: str) -> list[tuple[str, str]]:
    """Parse the ``plexPrefix=localPrefix`` pairs, longest Plex prefix first."""
    pairs: list[tuple[str, str]] = []
    for chunk in (raw or "").replace("\n", ",").split(","):
        chunk = chunk.strip()
        if not chunk or "=" not in chunk:
            continue
        plex, local = chunk.split("=", 1)
        plex, local = plex.strip(), local.strip()
        if plex and local:
            pairs.append((plex, local))
    pairs.sort(key=lambda p: len(p[0]), reverse=True)
    return pairs


def map_path(db: Session, plex_path: str) -> str:
    """Translate a Plex-side absolute path to the local mount path (no mapping = unchanged)."""
    for plex_prefix, local_prefix in parse_map(sysconfig.get_str(db, "plex_path_map")):
        if plex_path == plex_prefix or plex_path.startswith(plex_prefix.rstrip("/") + "/"):
            rest = plex_path[len(plex_prefix):].lstrip("/")
            return str(Path(local_prefix) / rest) if rest else local_prefix
    return plex_path


def local_media_path(db: Session, plex_path: str | None) -> Path | None:
    """The resolved, existing local file for a Plex media path, or None if it can't be read.
    The path originates from the trusted Plex server + an admin-set map (not user input), so no
    traversal check is needed beyond requiring a real regular file to exist."""
    if not plex_path:
        return None
    try:
        p = Path(map_path(db, plex_path)).resolve()
    except OSError:
        return None
    return p if p.is_file() else None
