"""Path utilities for session-based manifest management.

This module provides filesystem path helpers for session directories and manifest files.
Extracted to avoid circular dependencies between session_manifest and manifest_history modules.
"""

import hashlib
import re
import sys
from functools import lru_cache
from pathlib import Path

from connector_builder_mcp.constants import CONNECTOR_BUILDER_MCP_WORKSPACE_ID, SESSION_BASE_DIR


_WORKSPACE_SLUG_PATTERN = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")


def _validate_workspace_id(workspace_id: str) -> None:
    """Validate that a workspace ID is a valid slug.

    A valid slug contains only lowercase alphanumeric characters and hyphens,
    must not start or end with a hyphen, and must not contain consecutive hyphens.

    Args:
        workspace_id: Workspace ID to validate

    Raises:
        SystemExit: If the workspace ID is not a valid slug
    """
    if not _WORKSPACE_SLUG_PATTERN.match(workspace_id):
        print(
            f"ERROR: Invalid CONNECTOR_BUILDER_MCP_WORKSPACE_ID='{workspace_id}'. "
            "Must be a lowercase alphanumeric slug with hyphens only "
            "(e.g., 'local-connector-build', 'my-workspace-1').",
            file=sys.stderr,
        )
        sys.exit(1)


if CONNECTOR_BUILDER_MCP_WORKSPACE_ID is not None:
    _validate_workspace_id(CONNECTOR_BUILDER_MCP_WORKSPACE_ID)


def _sanitize_session_id(session_id: str) -> str:
    """Sanitize session ID to ensure it's filesystem-safe.

    Args:
        session_id: Raw session ID

    Returns:
        Filesystem-safe session ID (hashed)
    """
    return hashlib.sha256(session_id.encode()).hexdigest()


def get_workspace_id(session_id: str) -> str:
    """Get the effective workspace ID for this session.

    If CONNECTOR_BUILDER_MCP_WORKSPACE_ID is set, return the workspace slug.
    Otherwise, default to the (hashed) session ID as the workspace identifier.

    Args:
        session_id: Transport-layer session ID

    Returns:
        Workspace identifier to use as the session directory name
    """
    if CONNECTOR_BUILDER_MCP_WORKSPACE_ID is not None:
        return CONNECTOR_BUILDER_MCP_WORKSPACE_ID
    return _sanitize_session_id(session_id)


@lru_cache(maxsize=256)
def get_session_dir(session_id: str) -> Path:
    """Get the directory path for a session, ensuring it exists.

    DEPRECATED: This function uses the legacy SESSION_BASE_DIR constant.
    New code should use resolve_session_manifest_path() which respects
    environment variable overrides.

    This function is LRU cached to avoid repeated filesystem operations.
    The directory is created if it doesn't exist.

    Args:
        session_id: Session ID

    Returns:
        Path to the session directory (guaranteed to exist)
    """
    workspace_id = get_workspace_id(session_id)
    session_dir = SESSION_BASE_DIR / workspace_id
    session_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
    return session_dir


def resolve_session_manifest_path(session_id: str) -> Path:
    """Resolve the session manifest path.

    This is a thin wrapper around get_session_dir() for compatibility.
    Returns the manifest.yaml path within the session directory.

    Args:
        session_id: Session ID

    Returns:
        Path to the manifest file
    """
    return get_session_dir(session_id) / "manifest.yaml"


def get_session_manifest_path(session_id: str) -> Path:
    """Get the path to the session manifest file.

    Args:
        session_id: Session ID

    Returns:
        Path to the manifest.yaml file for the session
    """
    manifest_path = resolve_session_manifest_path(session_id)
    manifest_path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    return manifest_path


def get_session_checklist_path(session_id: str) -> Path:
    """Get the path to the session checklist file.

    Args:
        session_id: Session ID

    Returns:
        Path to the checklist.json file for the session
    """
    return get_session_dir(session_id) / "checklist.json"


def get_global_checklist_path() -> Path:
    """Get the path to the global checklist file."""
    return Path(__file__).parent / "_guidance" / "connector_build_checklist.yml"
