"""Metric naming conventions for GCP Cloud Monitoring compatibility.

This module defines the naming rules and validation functions for metric names.
It provides the core validation logic used by MetricNameValidator.
"""

import re

# Metric naming pattern (GCP Cloud Monitoring compatible)
# Must start with lowercase letter, followed by lowercase letters, digits, underscores, or dots
METRIC_NAME_PATTERN = re.compile(r"^[a-z][a-z0-9_.]*$")

# Constraints
MIN_METRIC_NAME_LENGTH = 3
MAX_METRIC_NAME_LENGTH = 256  # GCP limit


def is_valid_metric_name(name: str) -> bool:
    """Check if metric name follows naming convention.

    Rules:
    - Must start with lowercase letter (a-z)
    - May contain lowercase letters, digits, underscores, dots
    - Must NOT contain hyphens, spaces, uppercase, special chars
    - Length: 3-256 characters

    Examples:
        >>> is_valid_metric_name("model.predictions_total")  # True
        >>> is_valid_metric_name("valid_metric_name")  # True
        >>> is_valid_metric_name("invalid-name")  # False (hyphen)
        >>> is_valid_metric_name("123_invalid")  # False (starts with digit)
        >>> is_valid_metric_name("MetricName")  # False (uppercase)

    Args:
        name: Metric name to validate

    Returns:
        True if valid, False otherwise
    """
    if not name:
        return False

    if len(name) < MIN_METRIC_NAME_LENGTH or len(name) > MAX_METRIC_NAME_LENGTH:
        return False

    return METRIC_NAME_PATTERN.match(name) is not None


def sanitize_metric_name(name: str) -> str:
    """Sanitize invalid metric name for permissive mode.

    Transformations:
    - Replace hyphens and spaces with underscores
    - Convert to lowercase
    - Remove invalid characters (keep only a-z, 0-9, _, .)
    - Ensure starts with letter (prepend 'm_' if starts with digit)
    - Ensure minimum length (prepend 'metric_' if too short)
    - Truncate to maximum length if too long

    Examples:
        >>> sanitize_metric_name("invalid-name")  # "invalid_name"
        >>> sanitize_metric_name("123_metric")  # "m_123_metric"
        >>> sanitize_metric_name("MetricName")  # "metricname"
        >>> sanitize_metric_name("metric name")  # "metric_name"
        >>> sanitize_metric_name("ab")  # "metric_ab"

    Args:
        name: Original metric name

    Returns:
        Sanitized metric name that follows naming convention
    """
    # Replace hyphens and spaces with underscores
    sanitized = name.replace("-", "_").replace(" ", "_")

    # Convert to lowercase
    sanitized = sanitized.lower()

    # Remove invalid characters (keep only alphanumeric, underscore, dot)
    sanitized = re.sub(r"[^a-z0-9_.]", "", sanitized)

    # Ensure starts with letter
    if sanitized and sanitized[0].isdigit():
        sanitized = f"m_{sanitized}"

    # Ensure minimum length
    if len(sanitized) < MIN_METRIC_NAME_LENGTH:
        sanitized = f"metric_{sanitized}"

    # Ensure maximum length
    if len(sanitized) > MAX_METRIC_NAME_LENGTH:
        sanitized = sanitized[:MAX_METRIC_NAME_LENGTH]

    return sanitized
