# middleware/theme_context.py
"""
Theme Context Middleware (Class-Based)

Injects store-specific theme into request context.

Class-based middleware provides:
- Better state management
- Easier testing
- Standard ASGI pattern
"""

import logging

from fastapi import Request
from sqlalchemy.orm import Session
from starlette.middleware.base import BaseHTTPMiddleware

from app.core.database import get_db
from app.modules.cms.models import StoreTheme

logger = logging.getLogger(__name__)


class ThemeContextManager:
    """Manages theme context for store shops."""

    @staticmethod
    def get_store_theme(db: Session, store_id: int) -> dict:
        """
        Get theme configuration for store.
        Returns default theme if no custom theme is configured.
        """
        theme = (
            db.query(StoreTheme)
            .filter(StoreTheme.store_id == store_id, StoreTheme.is_active == True)
            .first()
        )

        if theme:
            return theme.to_dict()

        # Return default theme
        return ThemeContextManager.get_default_theme()

    @staticmethod
    def get_default_theme() -> dict:
        """Default theme configuration"""
        return {
            "theme_name": "default",
            "colors": {
                "primary": "#6366f1",
                "secondary": "#8b5cf6",
                "accent": "#ec4899",
                "background": "#ffffff",
                "text": "#1f2937",
                "border": "#e5e7eb",
            },
            "fonts": {"heading": "Inter, sans-serif", "body": "Inter, sans-serif"},
            "branding": {
                "logo": None,
                "logo_dark": None,
                "favicon": None,
                "banner": None,
            },
            "layout": {"style": "grid", "header": "fixed", "product_card": "modern"},
            "social_links": {},
            "custom_css": None,
            "css_variables": {
                "--color-primary": "#6366f1",
                "--color-secondary": "#8b5cf6",
                "--color-accent": "#ec4899",
                "--color-background": "#ffffff",
                "--color-text": "#1f2937",
                "--color-border": "#e5e7eb",
                "--font-heading": "Inter, sans-serif",
                "--font-body": "Inter, sans-serif",
            },
        }


class ThemeContextMiddleware(BaseHTTPMiddleware):
    """
    Middleware to inject theme context into request state.

    Class-based middleware provides:
    - Better state management
    - Easier testing
    - Standard ASGI pattern

    Runs LAST in middleware chain (after store_context_middleware and context_middleware).
    Depends on:
        request.state.store (set by store_context_middleware)

    Sets:
        request.state.theme: Theme dictionary
    """

    async def dispatch(self, request: Request, call_next):
        """
        Load and inject theme context.
        """
        # Only inject theme for shop pages (not admin or API)
        if hasattr(request.state, "store") and request.state.store:
            store = request.state.store

            # Get database session
            db_gen = get_db()
            db = next(db_gen)

            try:
                # Get store theme
                theme = ThemeContextManager.get_store_theme(db, store.id)
                request.state.theme = theme

                logger.debug(
                    "[THEME] Theme loaded for store",
                    extra={
                        "store_id": store.id,
                        "store_name": store.name,
                        "theme_name": theme.get("theme_name", "default"),
                    },
                )
            except Exception as e:
                logger.error(
                    f"[THEME] Failed to load theme for store {store.id}: {e}",
                    exc_info=True,
                )
                # Fallback to default theme
                request.state.theme = ThemeContextManager.get_default_theme()
            finally:
                db.close()
        else:
            # No store context, use default theme
            request.state.theme = ThemeContextManager.get_default_theme()
            logger.debug(
                "[THEME] No store context, using default theme",
                extra={"has_store": False},
            )

        # Continue processing
        response = await call_next(request)
        return response


def get_current_theme(request: Request) -> dict:
    """Helper function to get current theme from request state."""
    return getattr(request.state, "theme", ThemeContextManager.get_default_theme())
