"""Analytics generator for Prism backend.

Generates analytics infrastructure using a decorator/middleware pattern:
- @track_event decorator for automatic event tracking on service methods
- Analytics middleware for API call tracking
- SQLAlchemy models (AnalyticsEvent, AnalyticsSession)
- Analytics service for querying/aggregating data
- REST API routes for the analytics dashboard
"""

from __future__ import annotations

from pathlib import Path

from prisme.generators.base import GeneratedFile, GeneratorBase
from prisme.spec.stack import FileStrategy
from prisme.utils.template_engine import TemplateRenderer


class AnalyticsGenerator(GeneratorBase):
    """Generates backend analytics system with decorator-based tracking."""

    REQUIRED_TEMPLATES = [
        "backend/analytics/decorator.py.jinja2",
        "backend/analytics/middleware.py.jinja2",
        "backend/analytics/models.py.jinja2",
        "backend/analytics/schemas.py.jinja2",
        "backend/analytics/service.py.jinja2",
        "backend/analytics/routes.py.jinja2",
        "backend/analytics/analytics_init.py.jinja2",
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if not self.analytics_config.enabled:
            self.skip_generation = True
            return

        self.renderer = TemplateRenderer()
        self.renderer.validate_templates_exist(self.REQUIRED_TEMPLATES)

        backend_base = Path(self.generator_config.backend_output)
        package_name = self.get_package_name()
        package_base = backend_base / package_name

        self.analytics_base = package_base / "analytics"
        self.models_path = package_base / self.generator_config.models_path
        self.schemas_path = package_base / "schemas"
        self.routes_base = package_base / "api" / "rest"
        self.middleware_path = package_base / "middleware"

    def _get_common_context(self) -> dict:
        """Build the common template context from analytics config."""
        config = self.analytics_config
        project_name = self.get_package_name()

        ctx = {
            "project_name": project_name,
            # Tracking features
            "track_page_views": config.track_page_views,
            "track_user_sessions": config.track_user_sessions,
            "track_crud_events": config.track_crud_events,
            "track_api_calls": config.track_api_calls,
            # Decorator
            "decorator_name": config.decorator_name,
            # Middleware
            "middleware_enabled": config.middleware_enabled,
            # Privacy
            "anonymize_users": config.anonymize_users,
            "exclude_paths": config.exclude_paths,
            # Sessions
            "session_timeout_minutes": config.session.timeout_minutes,
            "track_device_info": config.session.track_device_info,
            "track_referrer": config.session.track_referrer,
            "track_geo": config.session.track_geo,
            # Dashboard
            "dashboard_enabled": config.dashboard.enabled,
            "dashboard_path": config.dashboard.path,
            "retention_days": config.dashboard.retention_days,
            # Google Analytics
            "has_google_analytics": config.has_google_analytics,
            "google_analytics": (
                config.google_analytics.model_dump() if config.google_analytics else None
            ),
            # Custom events
            "custom_events": [e.model_dump() for e in config.custom_events],
            "has_custom_events": config.has_custom_events,
            # Auth integration
            "auth_enabled": self._has_auth(),
        }
        return ctx

    def generate_files(self) -> list[GeneratedFile]:
        """Generate all analytics-related backend files."""
        if getattr(self, "skip_generation", False):
            return []

        files = []

        # Core: decorator
        files.append(self._generate_decorator())

        # Core: models
        files.append(self._generate_models())

        # Core: schemas
        files.append(self._generate_schemas())

        # Core: service
        files.append(self._generate_service())

        # Core: routes
        files.append(self._generate_routes())

        # Init file
        files.append(self._generate_init())

        # Conditional: middleware
        if self.analytics_config.middleware_enabled:
            files.append(self._generate_middleware())

        return files

    def _generate_decorator(self) -> GeneratedFile:
        """Generate the @track_event decorator."""
        content = self.renderer.render_file(
            "backend/analytics/decorator.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.analytics_base / "decorator.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics @track_event decorator",
        )

    def _generate_middleware(self) -> GeneratedFile:
        """Generate analytics collection middleware."""
        content = self.renderer.render_file(
            "backend/analytics/middleware.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.middleware_path / "analytics.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics middleware",
        )

    def _generate_models(self) -> GeneratedFile:
        """Generate SQLAlchemy analytics models."""
        content = self.renderer.render_file(
            "backend/analytics/models.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.models_path / "analytics.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics SQLAlchemy models",
        )

    def _generate_schemas(self) -> GeneratedFile:
        """Generate Pydantic schemas for analytics."""
        content = self.renderer.render_file(
            "backend/analytics/schemas.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.schemas_path / "analytics.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics Pydantic schemas",
        )

    def _generate_service(self) -> GeneratedFile:
        """Generate analytics query/aggregation service."""
        content = self.renderer.render_file(
            "backend/analytics/service.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.analytics_base / "service.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics service",
        )

    def _generate_routes(self) -> GeneratedFile:
        """Generate analytics REST API routes."""
        content = self.renderer.render_file(
            "backend/analytics/routes.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.routes_base / "analytics.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics API routes",
        )

    def _generate_init(self) -> GeneratedFile:
        """Generate __init__.py for analytics module."""
        content = self.renderer.render_file(
            "backend/analytics/analytics_init.py.jinja2",
            context=self._get_common_context(),
        )
        return GeneratedFile(
            path=self.analytics_base / "__init__.py",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Analytics module init",
        )

    def _has_auth(self) -> bool:
        """Check if authentication is enabled."""
        try:
            return self.auth_config.enabled
        except (ValueError, AttributeError):
            return False
