from __future__ import annotations

from pathlib import Path
from typing import Any


MANAGED_ROOT_NAMES = (
    "UserData",
    "LiveryLibrary",
    "LiveryProjects",
    "OfficialLiveryLibrary",
    "OfficialLiveryProjects",
    "LeagueLibrary",
    "LeagueProjects",
)


def managed_roots(storage_root: str | Path) -> dict[str, Path]:
    root = Path(storage_root).expanduser()
    return {name.lower(): root / name for name in MANAGED_ROOT_NAMES}


def _is_within(path: Path, root: Path) -> bool:
    try:
        path.resolve().relative_to(root.resolve())
        return True
    except Exception:
        return False


def rebase_managed_path(
    value: Any,
    storage_root: str | Path,
    *,
    expected_type: str = "any",
) -> str:
    text = str(value or "").strip()
    if not text:
        return ""
    current = Path(text).expanduser()
    if current.is_absolute() and current.exists():
        return str(current)

    roots = managed_roots(storage_root)
    parts = list(current.parts)
    root_index = next(
        (index for index in range(len(parts) - 1, -1, -1) if parts[index].lower() in roots),
        None,
    )
    if root_index is None:
        return text
    target_root = roots[parts[root_index].lower()]
    candidate = target_root.joinpath(*parts[root_index + 1 :])
    if not _is_within(candidate, target_root):
        return text
    if expected_type == "file" and not candidate.is_file():
        return text
    if expected_type == "dir" and not candidate.is_dir():
        return text
    if expected_type == "any" and not candidate.exists():
        return text
    return str(candidate)


def rebase_managed_paths(value: Any, storage_root: str | Path) -> Any:
    if isinstance(value, dict):
        return {str(key): rebase_managed_paths(item, storage_root) for key, item in value.items()}
    if isinstance(value, list):
        return [rebase_managed_paths(item, storage_root) for item in value]
    if isinstance(value, tuple):
        return [rebase_managed_paths(item, storage_root) for item in value]
    if isinstance(value, str):
        return rebase_managed_path(value, storage_root)
    return value
