"""Tests for the backend analytics generator."""

from __future__ import annotations

import pytest

from prisme.generators.backend.analytics import AnalyticsGenerator
from prisme.generators.base import GeneratorContext
from prisme.spec.analytics import AnalyticsConfig, CustomEventSpec, GoogleAnalyticsConfig
from prisme.spec.fields import FieldSpec, FieldType
from prisme.spec.model import ModelSpec
from prisme.spec.project import ProjectSpec
from prisme.spec.stack import FileStrategy, StackSpec


@pytest.fixture
def analytics_stack_spec() -> StackSpec:
    """Stack spec for analytics tests."""
    return StackSpec(
        name="test-app",
        models=[
            ModelSpec(
                name="Item",
                fields=[
                    FieldSpec(name="title", type=FieldType.STRING, required=True),
                ],
            ),
        ],
    )


@pytest.fixture
def analytics_enabled_project() -> ProjectSpec:
    """Project spec with analytics enabled."""
    return ProjectSpec(
        name="test-app",
        analytics=AnalyticsConfig(enabled=True),
    )


@pytest.fixture
def analytics_disabled_project() -> ProjectSpec:
    """Project spec with analytics disabled."""
    return ProjectSpec(
        name="test-app",
        analytics=AnalyticsConfig(enabled=False),
    )


@pytest.fixture
def analytics_full_project() -> ProjectSpec:
    """Project spec with full analytics config."""
    return ProjectSpec(
        name="test-app",
        analytics=AnalyticsConfig(
            enabled=True,
            track_page_views=True,
            track_user_sessions=True,
            track_crud_events=True,
            track_api_calls=True,
            google_analytics=GoogleAnalyticsConfig(),
            custom_events=[
                CustomEventSpec(name="signup_completed"),
                CustomEventSpec(name="purchase_made", category="ecommerce"),
            ],
        ),
    )


@pytest.fixture
def generator_context(
    analytics_stack_spec: StackSpec,
    analytics_enabled_project: ProjectSpec,
    tmp_path,
) -> GeneratorContext:
    return GeneratorContext(
        domain_spec=analytics_stack_spec,
        output_dir=tmp_path,
        dry_run=True,
        project_spec=analytics_enabled_project,
    )


@pytest.fixture
def generator_context_disabled(
    analytics_stack_spec: StackSpec,
    analytics_disabled_project: ProjectSpec,
    tmp_path,
) -> GeneratorContext:
    return GeneratorContext(
        domain_spec=analytics_stack_spec,
        output_dir=tmp_path,
        dry_run=True,
        project_spec=analytics_disabled_project,
    )


@pytest.fixture
def generator_context_full(
    analytics_stack_spec: StackSpec,
    analytics_full_project: ProjectSpec,
    tmp_path,
) -> GeneratorContext:
    return GeneratorContext(
        domain_spec=analytics_stack_spec,
        output_dir=tmp_path,
        dry_run=True,
        project_spec=analytics_full_project,
    )


class TestAnalyticsGenerator:
    """Tests for AnalyticsGenerator."""

    def test_skips_when_disabled(self, generator_context_disabled):
        """Generator returns empty list when analytics disabled."""
        generator = AnalyticsGenerator(generator_context_disabled)
        files = generator.generate_files()
        assert files == []

    def test_generates_files_when_enabled(self, generator_context):
        """Generator returns files when analytics enabled."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        assert len(files) > 0

    def test_generates_decorator(self, generator_context):
        """Generator produces the decorator file."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        decorator_files = [f for f in files if "decorator.py" in str(f.path)]
        assert len(decorator_files) == 1
        assert "track_event" in decorator_files[0].content

    def test_generates_models(self, generator_context):
        """Generator produces analytics models."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        model_files = [
            f for f in files if f.path.name == "analytics.py" and "models" in str(f.path)
        ]
        assert len(model_files) == 1
        assert "AnalyticsEvent" in model_files[0].content

    def test_generates_schemas(self, generator_context):
        """Generator produces analytics schemas."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        schema_files = [
            f for f in files if f.path.name == "analytics.py" and "schemas" in str(f.path)
        ]
        assert len(schema_files) == 1
        assert "EventCreate" in schema_files[0].content

    def test_generates_service(self, generator_context):
        """Generator produces analytics service."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        service_files = [f for f in files if "service.py" in str(f.path)]
        assert len(service_files) == 1
        assert "record_event" in service_files[0].content

    def test_generates_routes(self, generator_context):
        """Generator produces analytics routes."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        route_files = [f for f in files if f.path.name == "analytics.py" and "rest" in str(f.path)]
        assert len(route_files) == 1
        assert "router" in route_files[0].content

    def test_generates_middleware_when_enabled(self, generator_context):
        """Generator produces middleware when middleware_enabled=True."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        middleware_files = [f for f in files if "middleware" in str(f.path)]
        assert len(middleware_files) == 1
        assert "AnalyticsMiddleware" in middleware_files[0].content

    def test_generates_init(self, generator_context):
        """Generator produces __init__.py."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        init_files = [f for f in files if f.path.name == "__init__.py"]
        assert len(init_files) == 1

    def test_file_strategies(self, generator_context):
        """All generated files use ALWAYS_OVERWRITE strategy."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        for f in files:
            assert f.strategy == FileStrategy.ALWAYS_OVERWRITE

    def test_full_config_generates_all_files(self, generator_context_full):
        """Full analytics config generates decorator, middleware, models, schemas, service, routes, init."""
        generator = AnalyticsGenerator(generator_context_full)
        files = generator.generate_files()
        file_names = [f.path.name for f in files]
        assert "decorator.py" in file_names
        assert "__init__.py" in file_names
        assert "service.py" in file_names

    def test_session_tracking_in_models(self, generator_context):
        """Models include AnalyticsSession when track_user_sessions is True."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        model_files = [
            f for f in files if f.path.name == "analytics.py" and "models" in str(f.path)
        ]
        assert len(model_files) == 1
        assert "AnalyticsSession" in model_files[0].content

    def test_decorator_name_in_output(self, generator_context):
        """Decorator uses configured name."""
        generator = AnalyticsGenerator(generator_context)
        files = generator.generate_files()
        decorator_file = next(f for f in files if "decorator.py" in str(f.path))
        assert "def track_event(" in decorator_file.content
