# middleware/language.py
"""
Language detection middleware for multi-language support.

This middleware detects the appropriate language for each request based on:
- User/Customer preferences (from JWT token)
- Session/cookie language
- Store settings
- Browser Accept-Language header
- System default

The resolved language is stored in request.state.language for use in templates.
"""

import logging

from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response

from app.modules.enums import FrontendType
from app.utils.i18n import (
    DEFAULT_LANGUAGE,
    SUPPORTED_LANGUAGES,
    parse_accept_language,
    resolve_store_dashboard_language,
    resolve_storefront_language,
)

logger = logging.getLogger(__name__)

# Cookie name for language preference
LANGUAGE_COOKIE_NAME = "lang"


class LanguageMiddleware(BaseHTTPMiddleware):
    """
    Middleware to detect and set the request language.

    Sets request.state.language based on context:
    - Admin: Cookie → User preference → English
    - Merchant: Cookie → User preference → Platform default
    - Store dashboard: Cookie → User preference → Store dashboard_language → default
    - Storefront: Customer preference → Cookie → Store storefront_language → browser → default
    - Platform: Cookie → Browser → Platform default
    """

    async def dispatch(self, request: Request, call_next) -> Response:
        """Process the request and set language."""
        # Get frontend type from FrontendTypeMiddleware
        frontend_type = getattr(request.state, "frontend_type", None)

        # Get store from previous middleware (if available)
        store = getattr(request.state, "store", None)

        # Get language from cookie
        cookie_language = request.cookies.get(LANGUAGE_COOKIE_NAME)

        # Get browser language from Accept-Language header
        accept_language = request.headers.get("accept-language")
        browser_language = parse_accept_language(accept_language)

        # Resolve language based on frontend type
        if frontend_type == FrontendType.ADMIN:
            # Admin dashboard: cookie → user preference → English default
            user_preferred = self._get_user_language_from_token(request)
            language = cookie_language or user_preferred or "en"

        elif frontend_type == FrontendType.STORE:
            # Store dashboard
            user_preferred = self._get_user_language_from_token(request)
            store_dashboard = store.dashboard_language if store else None

            language = resolve_store_dashboard_language(
                user_preferred=user_preferred,
                store_dashboard=store_dashboard,
                cookie_language=cookie_language,
            )

        elif frontend_type == FrontendType.STOREFRONT:
            # Storefront
            customer_preferred = self._get_customer_language_from_token(request)
            store_storefront = store.storefront_language if store else None
            enabled_languages = store.storefront_languages if store else None

            language = resolve_storefront_language(
                customer_preferred=customer_preferred,
                session_language=cookie_language,
                store_storefront=store_storefront,
                browser_language=browser_language,
                enabled_languages=enabled_languages,
            )

        elif frontend_type == FrontendType.MERCHANT:
            # Merchant portal: cookie → user preference → platform default
            user_preferred = self._get_user_language_from_token(request)
            language = cookie_language or user_preferred or DEFAULT_LANGUAGE

        elif frontend_type == FrontendType.PLATFORM:
            # Platform marketing pages: Use cookie, browser, or default
            language = cookie_language or browser_language or DEFAULT_LANGUAGE

        else:
            # Fallback (API or unknown): Use Accept-Language or cookie
            language = cookie_language or browser_language or DEFAULT_LANGUAGE

        # Validate language is supported
        if language not in SUPPORTED_LANGUAGES:
            language = DEFAULT_LANGUAGE

        # Store language in request state
        request.state.language = language

        # Also store related info for templates
        request.state.language_info = {
            "code": language,
            "cookie": cookie_language,
            "browser": browser_language,
            "frontend_type": frontend_type.value if frontend_type else None,
        }

        # Log language detection for debugging
        frontend_value = frontend_type.value if frontend_type else "unknown"
        logger.debug(
            f"Language detected: {language} "
            f"(frontend={frontend_value}, cookie={cookie_language}, browser={browser_language})"
        )

        # Process request
        response = await call_next(request)

        return response

    def _get_user_language_from_token(self, request: Request) -> str | None:
        """
        Extract user's preferred_language from JWT token.

        This requires the auth middleware to have run first and stored
        user info in request.state.
        """
        # Check if user info is in request state (set by auth dependency)
        current_user = getattr(request.state, "current_user", None)
        if current_user and hasattr(current_user, "preferred_language"):
            return current_user.preferred_language

        return None

    def _get_customer_language_from_token(self, request: Request) -> str | None:
        """
        Extract customer's preferred_language from JWT token.

        This requires the shop auth middleware to have run first.
        """
        # Check if customer info is in request state
        current_customer = getattr(request.state, "current_customer", None)
        if current_customer and hasattr(current_customer, "preferred_language"):
            return current_customer.preferred_language

        return None


def set_language_cookie(response: Response, language: str) -> Response:
    """
    Helper function to set the language cookie on a response.

    Args:
        response: Response object to modify
        language: Language code to set

    Returns:
        Modified response with language cookie
    """
    if language in SUPPORTED_LANGUAGES:
        response.set_cookie(
            key=LANGUAGE_COOKIE_NAME,
            value=language,
            max_age=60 * 60 * 24 * 365,  # 1 year
            httponly=False,  # Accessible to JavaScript
            samesite="lax",
            path="/",
        )
    return response


def delete_language_cookie(response: Response) -> Response:
    """
    Helper function to delete the language cookie.

    Args:
        response: Response object to modify

    Returns:
        Modified response with cookie deleted
    """
    response.delete_cookie(key=LANGUAGE_COOKIE_NAME, path="/")
    return response
