"""Session folder path normalization and validation helpers for Studio."""

from __future__ import annotations

import re
from pathlib import Path, PurePosixPath

_SESSION_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")


def validate_session_name(name: str) -> str:
    """Validate a single session folder name (no path separators)."""
    candidate = (name or "").strip()
    if not candidate:
        raise ValueError("Session folder name is required")
    if candidate in {".", ".."}:
        raise ValueError("Invalid session folder name")
    if "/" in candidate or "\\" in candidate:
        raise ValueError("Session folder name cannot contain path separators")
    if not _SESSION_NAME_RE.fullmatch(candidate):
        raise ValueError(
            "Session folder name can only contain letters, numbers, '.', '_', and '-'"
        )
    return candidate


def normalize_session_folder_arg(session_folder: str) -> str:
    """Normalize session folder CLI/API input to '.mixer/sessions/<name>'."""
    raw = (session_folder or "").strip()
    if not raw:
        return ""

    raw = raw.replace("\\", "/")
    pure = PurePosixPath(raw)
    if pure.is_absolute():
        raise ValueError("session_folder must be relative")

    parts = pure.parts
    if not parts or any(part in {".", ".."} for part in parts):
        raise ValueError("Invalid session_folder path")

    name: str
    if len(parts) == 1:
        name = validate_session_name(parts[0])
    elif len(parts) == 2 and parts[0] == "sessions":
        name = validate_session_name(parts[1])
    elif len(parts) == 3 and parts[0] == ".mixer" and parts[1] == "sessions":
        name = validate_session_name(parts[2])
    else:
        raise ValueError(
            "session_folder must be '<name>' or '.mixer/sessions/<name>'"
        )

    return f".mixer/sessions/{name}"


def session_name_from_folder_arg(session_folder: str) -> str:
    """Extract validated session name from a session_folder argument."""
    normalized = normalize_session_folder_arg(session_folder)
    if not normalized:
        raise ValueError("session_folder is required")
    return PurePosixPath(normalized).name


def resolve_session_path(sessions_dir: Path, name: str) -> Path:
    """Resolve and validate a session path under sessions_dir."""
    root = sessions_dir.resolve()
    validated = validate_session_name(name)
    candidate = (root / validated).resolve()
    if candidate.parent != root:
        raise ValueError("Invalid session folder path")
    return candidate
