"""
Localization service for UI Router.

This module provides the LocalizationService which manages Fluent localization
bundles and converts localized content to Fluent format.
"""

import hashlib
import logging
from typing import Any

try:
    from fluent.runtime import FluentBundle, FluentResource
except ImportError:
    FluentBundle = None  # type: ignore[assignment]
    FluentResource = None  # type: ignore[assignment]

from ui_router.schema import UIRouter, LocalizedTemplate, DynamicContent

logger = logging.getLogger(__name__)


class LocalizationService:
    """
    Service for managing Fluent localization.

    Responsible for:
    - Building Fluent bundles from schema
    - Collecting translations from flags and content
    - Converting templates to Fluent format
    - Reloading bundles when schema is updated
    """

    def __init__(self, schema: UIRouter, enable_fluent: bool = False) -> None:
        """
        Initialize LocalizationService.

        Args:
            schema: UIRouter schema containing scenes and content.
            enable_fluent: Whether to enable Fluent localization.
        """
        self.schema = schema
        self.enable_fluent = enable_fluent
        self.fluent_bundles: dict[str, Any] | None = None

        if self.enable_fluent:
            self._build_fluent_bundles()

    def _build_fluent_bundles(self) -> None:
        """
        Build Fluent bundles from schema.

        Collects all localized content and templates from the schema and
        creates FluentBundle instances for each locale. Requires fluent.runtime
        to be installed.
        """
        if FluentBundle is None or FluentResource is None:
            logger.warning("Warning: fluent.runtime not installed. Install with: pip install fluent.runtime")
            self.enable_fluent = False
            return

        messages_by_locale: dict[str, list[str]] = {}

        for flag in self.schema.global_flags:
            self._collect_from_flag(flag, messages_by_locale)

        for scene in self.schema.scenes:
            for flag in scene.flags:
                self._collect_from_flag(flag, messages_by_locale)

            if scene.default_content and scene.default_content.text:
                self._collect_from_content(scene.default_content.text, messages_by_locale)

            if scene.default_keyboard:
                for row in scene.default_keyboard.buttons:
                    for btn in row:
                        self._collect_from_content(btn.text, messages_by_locale)

        self.fluent_bundles = {}
        for locale, messages in messages_by_locale.items():
            bundle = FluentBundle([locale])
            ftl_text = "\n".join(messages)
            resource = FluentResource(ftl_text)
            bundle.add_resource(resource)
            self.fluent_bundles[locale] = bundle

        logger.debug(
            "Fluent bundles created for locales: %s",
            list(self.fluent_bundles.keys()),
        )

    def _collect_from_flag(self, flag: Any, messages_by_locale: dict[str, list[str]]) -> None:
        """
        Collect Fluent messages from a flag.

        Flags typically don't contain localization directly, so this is
        a placeholder for potential future use.

        Args:
            flag: Flag object from schema.
            messages_by_locale: Dictionary to accumulate messages by locale.
        """

    def _collect_from_content(self, content: Any, messages_by_locale: dict[str, list[str]]) -> None:
        """
        Collect Fluent messages from content.

        Handles LocalizedContent and DynamicContent with localized templates,
        converting them to Fluent format.

        Args:
            content: Content object (LocalizedContent, DynamicContent, or string).
            messages_by_locale: Dictionary to accumulate messages by locale.
        """
        if isinstance(content, DynamicContent) and (
            content.type == "localized_template" and content.localized_template
        ):
            template = content.localized_template
            fluent_id = self._get_fluent_id(template)

            for locale, text in template.translations.items():
                fluent_text = self._convert_to_fluent_format(text, template.flags)
                fluent_message = f"{fluent_id} = {fluent_text}"

                if locale not in messages_by_locale:
                    messages_by_locale[locale] = []
                messages_by_locale[locale].append(fluent_message)

    def _get_fluent_id(self, template: LocalizedTemplate) -> str:
        """
        Generate unique Fluent ID for template.

        Creates an ID based on MD5 hash of English text (or first available
        translation) to ensure consistency across reloads.

        Args:
            template: LocalizedTemplate object.

        Returns:
            Fluent message ID string.
        """
        base_text = template.translations.get("en") or next(iter(template.translations.values()))
        # MD5 is used here only for deterministic ID generation, not for security
        hash_str = hashlib.md5(base_text.encode(), usedforsecurity=False).hexdigest()[:12]
        return f"msg_{hash_str}"

    def _convert_to_fluent_format(self, text: str, flags: list[str]) -> str:
        """
        Convert Python format {name} to Fluent format { $name }.

        Replaces Python string format placeholders with Fluent parameter
        syntax for use in localization.

        Args:
            text: Text with Python format placeholders.
            flags: List of flag names to convert.

        Returns:
            Text with converted Fluent format placeholders.
        """
        result = text
        for flag in flags:
            result = result.replace(f"{{{flag}}}", f"{{ ${flag} }}")
        return result

    def reload_fluent_bundles(self) -> None:
        """
        Reload Fluent bundles from schema.

        Clears existing bundles and rebuilds them. Used for hot reload
        after schema changes.
        """
        if not self.enable_fluent:
            logger.debug("Fluent is disabled, cannot reload")
            return

        logger.debug("Reloading Fluent bundles...")
        if self.fluent_bundles:
            self.fluent_bundles.clear()
        self._build_fluent_bundles()

        logger.debug("Fluent bundles reloaded successfully")

    def get_bundle(self, locale: str) -> Any | None:
        """
        Get Fluent bundle for specific locale.

        Args:
            locale: Locale code (e.g., 'en', 'ru').

        Returns:
            FluentBundle instance for the locale or None if not available.
        """
        if not self.fluent_bundles:
            return None
        return self.fluent_bundles.get(locale)
