# acmenra_cv/render/style/fill.py

import logging
from typing import List, Dict, Any


logger = logging.getLogger(__name__)


class Fill:
    """
    Configuration for shape fills.

    If `Style.fill` is set to `None`, no interior fill is drawn.
    When present, uses `palette[class_id]` for color combined with this parameter.

    Attributes:
        alpha (float): Fill opacity [0.0, 1.0].
    """

    def __init__(self, alpha: float = 0.35):  # tested (good)
        """
        Initializes fill configuration with validation.

        Args:
            alpha (float, optional): Fill opacity [0.0, 1.0]. Defaults to 0.35.

        Raises:
            TypeError: If alpha is not a float.
            ValueError: If alpha is outside [0.0, 1.0].
        """
        self.alpha = alpha

    def __str__(self) -> str: # tested (good)
        """
        Returns a human-readable string representation of the fill configuration.

        Returns:
            str: Concise summary with fill opacity level.
                 Format: "Fill(alpha=0.35)"

        Note:
            - Optimized for console logging, operator dashboards, and alert systems
            - Uses fixed-point precision for immediate visual clarity
            - Omits internal validation state for brevity
        """
        return f"Fill(alpha={self.alpha:.2f})"

    def __repr__(self) -> str: # tested (good)
        """
        Returns a detailed string representation suitable for debugging and reproduction.

        Returns:
            str: Exact representation including the canonical alpha parameter.
                 Uses repr-safe formatting (!r) for unambiguous parsing.

        Note:
            - Output can theoretically be used to recreate the object in interactive sessions
            - Preserves full floating-point precision for state traceability
            - Essential for debugging pipeline style overrides and validation failures
        """
        return f"Fill(alpha={self.alpha!r})"

    @property
    def alpha(self) -> float: # tested (good)
        """
        float: Gets the fill opacity level.

        Returns:
            float: Opacity value in range [0.0, 1.0].

        Note:
            - 0.0 = fully transparent (invisible fill).
            - 1.0 = fully opaque solid fill.
            - This value is multiplied with global Style.alpha during compositing.
            - Controls how much of the underlying video frame shows through filled shapes.
        """
        return self._alpha

    @alpha.setter
    def alpha(self, alpha: float) -> None: # tested (good)
        """
        Sets the fill opacity with range validation.

        Args:
            alpha (float): Opacity value to set. Must be in [0.0, 1.0].

        Raises:
            TypeError: If alpha is not a float.
            ValueError: If alpha is outside [0.0, 1.0].

        Note:
            - Values > 1.0 or < 0.0 are rejected as invalid.
            - Lower values allow underlying video frame or other overlays to show through.
            - Combined with stroke.alpha for layered transparency effects in ADAS rendering.
            - Changes affect all subsequent fill rendering operations immediately.
        """
        if not isinstance(alpha, float):
            raise TypeError(f"'alpha' must be '<float>', but got {type(alpha).__name__}")
        if not 0.0 <= alpha <= 1.0:
            raise ValueError(f"'alpha' must be in [0.0, 1.0], got {alpha}")
        self._alpha = alpha

    def to_dict(self) -> Dict[str, Any]: # tested (good)
        """
        Serializes the Fill configuration to a JSON-compatible dictionary.

        Returns:
            Dict[str, Any]: Dictionary containing the fill opacity parameter.

        Note:
            - Ready for direct DB insertion or API transmission.
            - Preserves full floating-point precision for alpha value.
            - Maintains perfect round-trip fidelity with from_dict().
        """
        return {
            "alpha": self.alpha
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Fill': # tested (good)
        """
        Reconstructs a Fill instance from a serialized dictionary.

        Args:
            data: Dictionary with fill configuration. Required: alpha.

        Returns:
            Fill: Fully initialized and validated instance.

        Raises:
            KeyError: If alpha is missing from input dictionary.
            TypeError: If alpha is not a valid float.
            ValueError: If alpha is outside [0.0, 1.0].

        Note:
            - Delegates validation to property setters.
            - Handles missing keys safely with None defaults (except required fields).
            - Maintains perfect round-trip fidelity with to_dict().
        """
        required_fields = ['alpha']
        for field in required_fields:
            if field not in data:
                raise KeyError(f"Required field '{field}' is missing from input dictionary: {data}")

        return cls(
            alpha=float(data.get("alpha"))
        )
