"""Shared skill name and path validation.

Extracted from ``cli/skills_commands.py`` so both the CLI and the
installer can reuse the same rules without import-time side effects.
"""

from __future__ import annotations

from pathlib import Path

MAX_SKILL_NAME_LENGTH = 64


def validate_skill_name(name: str) -> tuple[bool, str]:
    """Validate name per Agent Skills spec.

    Requirements (https://agentskills.io/specification):
    - Max 64 characters
    - Unicode lowercase alphanumeric and hyphens only
    - Cannot start or end with hyphen
    - No consecutive hyphens
    - No path traversal sequences

    Args:
        name: The name to validate.

    Returns:
        Tuple of (is_valid, error_message). If valid, error_message is empty.
    """
    if not name or not name.strip():
        return False, "cannot be empty"

    if len(name) > MAX_SKILL_NAME_LENGTH:
        return False, "cannot exceed 64 characters"

    if ".." in name or "/" in name or "\\" in name:
        return False, "cannot contain path components"

    if name.startswith("-") or name.endswith("-") or "--" in name:
        return (
            False,
            "must be lowercase alphanumeric with single hyphens only",
        )

    for c in name:
        if c == "-":
            continue
        if (c.isalpha() and c.islower()) or c.isdigit():
            continue
        return (
            False,
            "must be lowercase alphanumeric with single hyphens only",
        )

    return True, ""


MAX_PLUGIN_NAME_LENGTH = 100


def validate_plugin_name(name: str) -> tuple[bool, str]:
    """Validate a plugin (registry) name for safe use as a directory component.

    More permissive than skill names — allows uppercase, dots, and
    underscores to match GitHub repository naming rules.  Rejects path
    traversal sequences and characters that are unsafe in directory names.

    Args:
        name: The plugin name to validate.

    Returns:
        Tuple of (is_valid, error_message). If valid, error_message is empty.
    """
    if not name or not name.strip():
        return False, "cannot be empty"

    if len(name) > MAX_PLUGIN_NAME_LENGTH:
        return False, f"cannot exceed {MAX_PLUGIN_NAME_LENGTH} characters"

    if ".." in name or "/" in name or "\\" in name:
        return False, "cannot contain path components"

    if name in (".", "~"):
        return False, "reserved name"

    for c in name:
        if c.isalnum() or c in "-_.":
            continue
        return False, "must contain only alphanumeric, hyphens, dots, or underscores"

    return True, ""


def validate_skill_path(skill_dir: Path, base_dir: Path) -> tuple[bool, str]:
    """Validate that the resolved skill directory is within the base directory.

    Args:
        skill_dir: The skill directory path to validate.
        base_dir: The base skills directory that should contain skill_dir.

    Returns:
        Tuple of (is_valid, error_message). If valid, error_message is empty.
    """
    try:
        resolved_skill = skill_dir.resolve()
        resolved_base = base_dir.resolve()

        if not resolved_skill.is_relative_to(resolved_base):
            return False, f"Skill directory must be within {base_dir}"
    except (OSError, RuntimeError) as e:
        return False, f"Invalid path: {e}"
    else:
        return True, ""
