"""Tests for analytics configuration specification."""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from prisme.spec.analytics import (
    AnalyticsConfig,
    CustomEventSpec,
    DashboardConfig,
    GoogleAnalyticsConfig,
    SessionConfig,
)


class TestCustomEventSpec:
    """Tests for CustomEventSpec validation."""

    def test_valid_event(self):
        event = CustomEventSpec(name="purchase_completed", category="ecommerce")
        assert event.name == "purchase_completed"
        assert event.category == "ecommerce"

    def test_event_with_properties(self):
        event = CustomEventSpec(
            name="button_clicked",
            properties=["button_id", "page"],
            description="User clicked a button",
        )
        assert event.properties == ["button_id", "page"]
        assert event.description == "User clicked a button"

    def test_event_name_must_be_snake_case(self):
        with pytest.raises(ValidationError, match="snake_case"):
            CustomEventSpec(name="PurchaseCompleted")

    def test_event_name_rejects_leading_number(self):
        with pytest.raises(ValidationError, match="snake_case"):
            CustomEventSpec(name="1st_event")

    def test_event_name_rejects_dashes(self):
        with pytest.raises(ValidationError, match="snake_case"):
            CustomEventSpec(name="my-event")

    def test_default_category(self):
        event = CustomEventSpec(name="test_event")
        assert event.category == "custom"


class TestGoogleAnalyticsConfig:
    """Tests for GoogleAnalyticsConfig."""

    def test_defaults(self):
        ga = GoogleAnalyticsConfig()
        assert ga.measurement_id_env == "GA_MEASUREMENT_ID"
        assert ga.send_page_views is True
        assert ga.anonymize_ip is True
        assert ga.cookie_consent_required is True

    def test_custom_config(self):
        ga = GoogleAnalyticsConfig(
            measurement_id_env="MY_GA_ID",
            send_page_views=False,
            anonymize_ip=False,
            cookie_consent_required=False,
        )
        assert ga.measurement_id_env == "MY_GA_ID"
        assert ga.send_page_views is False

    def test_rejects_extra_fields(self):
        with pytest.raises(ValidationError):
            GoogleAnalyticsConfig(unknown_field="value")


class TestSessionConfig:
    """Tests for SessionConfig."""

    def test_defaults(self):
        session = SessionConfig()
        assert session.timeout_minutes == 30
        assert session.track_device_info is True
        assert session.track_referrer is True
        assert session.track_geo is False

    def test_timeout_bounds(self):
        with pytest.raises(ValidationError):
            SessionConfig(timeout_minutes=0)
        with pytest.raises(ValidationError):
            SessionConfig(timeout_minutes=1441)

    def test_valid_timeout(self):
        session = SessionConfig(timeout_minutes=60)
        assert session.timeout_minutes == 60


class TestDashboardConfig:
    """Tests for DashboardConfig."""

    def test_defaults(self):
        dashboard = DashboardConfig()
        assert dashboard.enabled is True
        assert dashboard.path == "/analytics"
        assert dashboard.retention_days == 90

    def test_retention_bounds(self):
        with pytest.raises(ValidationError):
            DashboardConfig(retention_days=0)
        with pytest.raises(ValidationError):
            DashboardConfig(retention_days=3651)


class TestAnalyticsConfig:
    """Tests for AnalyticsConfig."""

    def test_defaults_disabled(self):
        config = AnalyticsConfig()
        assert config.enabled is False
        assert config.track_page_views is True
        assert config.track_user_sessions is True
        assert config.track_crud_events is True
        assert config.track_api_calls is False
        assert config.google_analytics is None
        assert config.decorator_name == "track_event"

    def test_enabled_with_defaults(self):
        config = AnalyticsConfig(enabled=True)
        assert config.enabled is True
        assert config.has_google_analytics is False
        assert config.has_custom_events is False

    def test_with_google_analytics(self):
        config = AnalyticsConfig(
            enabled=True,
            google_analytics=GoogleAnalyticsConfig(),
        )
        assert config.has_google_analytics is True
        assert config.google_analytics is not None
        assert config.google_analytics.measurement_id_env == "GA_MEASUREMENT_ID"

    def test_with_custom_events(self):
        config = AnalyticsConfig(
            enabled=True,
            custom_events=[
                CustomEventSpec(name="signup_completed"),
                CustomEventSpec(name="purchase_made", category="ecommerce"),
            ],
        )
        assert config.has_custom_events is True
        assert len(config.custom_events) == 2

    def test_duplicate_event_names_rejected(self):
        with pytest.raises(ValidationError, match="Duplicate"):
            AnalyticsConfig(
                enabled=True,
                custom_events=[
                    CustomEventSpec(name="test_event"),
                    CustomEventSpec(name="test_event"),
                ],
            )

    def test_invalid_decorator_name(self):
        with pytest.raises(ValidationError, match="valid Python identifier"):
            AnalyticsConfig(enabled=True, decorator_name="track-event")

    def test_track_api_calls_requires_middleware(self):
        with pytest.raises(ValidationError, match="middleware_enabled"):
            AnalyticsConfig(
                enabled=True,
                track_api_calls=True,
                middleware_enabled=False,
            )

    def test_track_api_calls_with_middleware_ok(self):
        config = AnalyticsConfig(
            enabled=True,
            track_api_calls=True,
            middleware_enabled=True,
        )
        assert config.track_api_calls is True

    def test_validation_skipped_when_disabled(self):
        # Should not raise even though track_api_calls=True and middleware=False
        config = AnalyticsConfig(
            enabled=False,
            track_api_calls=True,
            middleware_enabled=False,
        )
        assert config.enabled is False

    def test_exclude_paths_default(self):
        config = AnalyticsConfig()
        assert "/health" in config.exclude_paths
        assert "/docs" in config.exclude_paths

    def test_rejects_extra_fields(self):
        with pytest.raises(ValidationError):
            AnalyticsConfig(enabled=True, unknown_field="value")

    def test_session_config(self):
        config = AnalyticsConfig(
            enabled=True,
            session=SessionConfig(timeout_minutes=60, track_geo=True),
        )
        assert config.session.timeout_minutes == 60
        assert config.session.track_geo is True

    def test_dashboard_config(self):
        config = AnalyticsConfig(
            enabled=True,
            dashboard=DashboardConfig(enabled=False),
        )
        assert config.dashboard.enabled is False
