"""Analytics configuration specification.

This module defines the analytics and tracking configuration
for Prism-generated applications. Supports:
- Built-in analytics (user tracking, sessions, events)
- Google Analytics integration
- Backend decorators for automatic event tracking
- Frontend macros for component-level tracking
"""

from __future__ import annotations

import re

from pydantic import BaseModel, Field, field_validator, model_validator


class GoogleAnalyticsConfig(BaseModel):
    """Google Analytics configuration.

    Example:
        ```python
        from prisme.spec.analytics import GoogleAnalyticsConfig

        ga = GoogleAnalyticsConfig(
            measurement_id_env="GA_MEASUREMENT_ID",
            send_page_views=True,
        )
        ```
    """

    measurement_id_env: str = Field(
        default="GA_MEASUREMENT_ID",
        description="Environment variable for Google Analytics measurement ID (G-XXXXXXXXXX)",
    )
    send_page_views: bool = Field(
        default=True,
        description="Automatically send page view events on navigation",
    )
    anonymize_ip: bool = Field(
        default=True,
        description="Anonymize user IP addresses in GA",
    )
    cookie_consent_required: bool = Field(
        default=True,
        description="Require cookie consent before loading GA",
    )

    model_config = {"extra": "forbid"}


class CustomEventSpec(BaseModel):
    """Custom analytics event definition.

    Example:
        ```python
        from prisme.spec.analytics import CustomEventSpec

        event = CustomEventSpec(
            name="purchase_completed",
            category="ecommerce",
            properties=["product_id", "amount", "currency"],
        )
        ```
    """

    name: str = Field(
        ...,
        description="Event name (snake_case)",
    )
    category: str = Field(
        default="custom",
        description="Event category for grouping",
    )
    properties: list[str] = Field(
        default_factory=list,
        description="Expected property names for this event",
    )
    description: str | None = Field(
        default=None,
        description="Human-readable event description",
    )

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str) -> str:
        """Validate event name is snake_case."""
        if not re.match(r"^[a-z][a-z0-9_]*$", v):
            raise ValueError(
                f"Event name '{v}' must be snake_case (lowercase, underscores, start with letter)"
            )
        return v

    model_config = {"extra": "forbid"}


class SessionConfig(BaseModel):
    """Session tracking configuration."""

    timeout_minutes: int = Field(
        default=30,
        description="Session timeout in minutes of inactivity",
        ge=1,
        le=1440,
    )
    track_device_info: bool = Field(
        default=True,
        description="Track user agent and device information",
    )
    track_referrer: bool = Field(
        default=True,
        description="Track referrer URL for sessions",
    )
    track_geo: bool = Field(
        default=False,
        description="Track geographic information (requires GeoIP)",
    )

    model_config = {"extra": "forbid"}


class DashboardConfig(BaseModel):
    """Analytics admin dashboard configuration."""

    enabled: bool = Field(
        default=True,
        description="Generate analytics admin dashboard",
    )
    path: str = Field(
        default="/analytics",
        description="Dashboard URL path in admin panel",
    )
    retention_days: int = Field(
        default=90,
        description="Default data retention period in days",
        ge=1,
        le=3650,
    )

    model_config = {"extra": "forbid"}


class AnalyticsConfig(BaseModel):
    """Analytics and tracking configuration.

    Controls analytics behavior for the entire application.
    When enabled, generates:
    - Backend: @track_event decorator, analytics middleware, models, API routes
    - Frontend: useAnalytics() hook, <TrackView> macro component, GA integration

    Example (full analytics with GA):
        ```python
        from prisme.spec.analytics import AnalyticsConfig, GoogleAnalyticsConfig

        analytics = AnalyticsConfig(
            enabled=True,
            track_page_views=True,
            track_user_sessions=True,
            google_analytics=GoogleAnalyticsConfig(
                measurement_id_env="GA_MEASUREMENT_ID",
            ),
        )
        ```

    Example (built-in only):
        ```python
        analytics = AnalyticsConfig(
            enabled=True,
            track_page_views=True,
            track_crud_events=True,
        )
        ```
    """

    # Core Settings
    enabled: bool = Field(
        default=False,
        description="Enable analytics system (opt-in for backward compatibility)",
    )

    # Tracking Features
    track_page_views: bool = Field(
        default=True,
        description="Track page views on the frontend",
    )
    track_user_sessions: bool = Field(
        default=True,
        description="Track user sessions with start/end timestamps",
    )
    track_crud_events: bool = Field(
        default=True,
        description="Auto-track CRUD operations via @track_event decorator",
    )
    track_api_calls: bool = Field(
        default=False,
        description="Track all API endpoint calls via middleware",
    )

    # Google Analytics
    google_analytics: GoogleAnalyticsConfig | None = Field(
        default=None,
        description="Google Analytics configuration (None = disabled)",
    )

    # Sessions
    session: SessionConfig = Field(
        default_factory=SessionConfig,
        description="Session tracking configuration",
    )

    # Custom Events
    custom_events: list[CustomEventSpec] = Field(
        default_factory=list,
        description="Custom event definitions",
    )

    # Dashboard
    dashboard: DashboardConfig = Field(
        default_factory=DashboardConfig,
        description="Analytics admin dashboard configuration",
    )

    # Backend Settings
    decorator_name: str = Field(
        default="track_event",
        description="Name of the Python decorator for event tracking",
    )
    middleware_enabled: bool = Field(
        default=True,
        description="Enable analytics collection middleware",
    )

    # Data Settings
    anonymize_users: bool = Field(
        default=False,
        description="Hash user identifiers for privacy",
    )
    exclude_paths: list[str] = Field(
        default_factory=lambda: ["/health", "/metrics", "/docs", "/openapi.json"],
        description="URL paths to exclude from tracking",
    )

    @field_validator("custom_events")
    @classmethod
    def validate_unique_event_names(cls, v: list[CustomEventSpec]) -> list[CustomEventSpec]:
        """Validate that custom event names are unique."""
        names = [e.name for e in v]
        if len(names) != len(set(names)):
            duplicates = [n for n in names if names.count(n) > 1]
            raise ValueError(f"Duplicate custom event names: {set(duplicates)}")
        return v

    @field_validator("decorator_name")
    @classmethod
    def validate_decorator_name(cls, v: str) -> str:
        """Validate decorator name is a valid Python identifier."""
        if not v.isidentifier():
            raise ValueError(f"Decorator name '{v}' must be a valid Python identifier")
        return v

    @model_validator(mode="after")
    def validate_config(self) -> AnalyticsConfig:
        """Validate analytics configuration consistency."""
        if not self.enabled:
            return self
        if self.track_api_calls and not self.middleware_enabled:
            raise ValueError("track_api_calls requires middleware_enabled=True")
        return self

    @property
    def has_google_analytics(self) -> bool:
        """Whether Google Analytics is configured."""
        return self.google_analytics is not None

    @property
    def has_custom_events(self) -> bool:
        """Whether custom events are defined."""
        return len(self.custom_events) > 0

    model_config = {"extra": "forbid"}


__all__ = [
    "AnalyticsConfig",
    "CustomEventSpec",
    "DashboardConfig",
    "GoogleAnalyticsConfig",
    "SessionConfig",
]
