"""
UI semantic layout types for DAZZLE IR.

This module contains layout engine specifications including
layout signals, workspace layouts, persona layouts, archetypes,
surfaces, and layout plans.
"""

from enum import StrEnum
from typing import Any

from pydantic import BaseModel, Field, field_validator


class AttentionSignalKind(StrEnum):
    """
    Semantic kinds of UI attention signals.

    Each kind represents a distinct UI interaction pattern that requires
    specific layout treatment.
    """

    KPI = "kpi"  # Key metric/number requiring visual prominence
    ALERT_FEED = "alert_feed"  # Stream of notifications/alerts
    TABLE = "table"  # Tabular data grid
    ITEM_LIST = "item_list"  # Vertical list of items
    DETAIL_VIEW = "detail_view"  # Full details of single item
    TASK_LIST = "task_list"  # Actionable task items
    FORM = "form"  # Input form for data entry
    CHART = "chart"  # Data visualization
    SEARCH = "search"  # Search interface
    FILTER = "filter"  # Filter controls


class LayoutSignal(BaseModel):
    """
    Semantic UI element requiring user attention in the layout engine.

    A layout signal represents a logical UI element that the user needs to
    be aware of and potentially interact with. Signals are allocated to surfaces
    by the layout engine based on their characteristics.

    Note: This is distinct from AttentionSignal (in ux.py) which is for DSL-based
    data-driven attention signals with conditions and messages.

    Attributes:
        id: Unique signal identifier
        kind: Semantic kind of signal
        label: Human-readable label
        source: Entity/surface reference that provides data
        attention_weight: Relative importance (0.0-1.0, higher = more important)
        urgency: How quickly user needs to respond
        interaction_frequency: How often user interacts with this signal
        density_preference: Preferred information density
        mode: Primary interaction mode
        constraints: Additional constraints (e.g., min_width, max_items)
    """

    model_config = {"frozen": True}

    id: str
    kind: AttentionSignalKind
    label: str
    source: str  # Entity or surface name
    attention_weight: float = Field(default=0.5, ge=0.0, le=1.0)
    urgency: str = "medium"  # low, medium, high
    interaction_frequency: str = "occasional"  # rare, occasional, frequent
    density_preference: str = "comfortable"  # compact, comfortable, spacious
    mode: str = "read"  # read, act, configure
    constraints: dict[str, Any] = Field(default_factory=dict)

    @field_validator("urgency")
    @classmethod
    def validate_urgency(cls, v: str) -> str:
        """Validate urgency is one of allowed values."""
        if v not in ("low", "medium", "high"):
            raise ValueError(f"urgency must be low/medium/high, got: {v}")
        return v

    @field_validator("interaction_frequency")
    @classmethod
    def validate_interaction_frequency(cls, v: str) -> str:
        """Validate interaction frequency is one of allowed values."""
        if v not in ("rare", "occasional", "frequent"):
            raise ValueError(f"interaction_frequency must be rare/occasional/frequent, got: {v}")
        return v

    @field_validator("density_preference")
    @classmethod
    def validate_density_preference(cls, v: str) -> str:
        """Validate density preference is one of allowed values."""
        if v not in ("compact", "comfortable", "spacious"):
            raise ValueError(f"density_preference must be compact/comfortable/spacious, got: {v}")
        return v

    @field_validator("mode")
    @classmethod
    def validate_mode(cls, v: str) -> str:
        """Validate mode is one of allowed values."""
        if v not in ("read", "act", "configure"):
            raise ValueError(f"mode must be read/act/configure, got: {v}")
        return v


class WorkspaceLayout(BaseModel):
    """
    Layout-enriched workspace definition.

    Extends the basic workspace concept with layout-specific metadata used
    by the layout engine to determine optimal UI structure.

    Attributes:
        id: Workspace identifier
        label: Human-readable label
        persona_targets: List of persona IDs this workspace is optimized for
        attention_budget: Total attention capacity (1.0 = normal, >1.0 = dense)
        time_horizon: Temporal focus of workspace
        stage: Layout stage hint (e.g., "scanner_table", "dual_pane_flow")
        stage_options: Stage-specific customization options
            - hero_height: "tall" | "medium" | "compact" (for FOCUS_METRIC)
            - context_columns: int (for FOCUS_METRIC)
            - show_empty_slots: bool
            - table_density: "comfortable" | "compact" (for SCANNER_TABLE)
        attention_signals: List of signals to display in this workspace
    """

    model_config = {"frozen": True}

    id: str
    label: str
    persona_targets: list[str] = Field(default_factory=list)
    attention_budget: float = Field(default=1.0, ge=0.0, le=1.5)
    time_horizon: str = "daily"  # realtime, daily, archival
    stage: str | None = None  # v0.8.0: Renamed from engine_hint
    stage_options: dict[str, Any] = Field(default_factory=dict)
    attention_signals: list[LayoutSignal] = Field(default_factory=list)

    @field_validator("time_horizon")
    @classmethod
    def validate_time_horizon(cls, v: str) -> str:
        """Validate time horizon is one of allowed values."""
        if v not in ("realtime", "daily", "archival"):
            raise ValueError(f"time_horizon must be realtime/daily/archival, got: {v}")
        return v


class PersonaLayout(BaseModel):
    """
    Layout-enriched persona definition.

    Extends the basic persona concept with UI preference biases used by
    the layout engine to optimize interfaces for specific user roles.

    Attributes:
        id: Persona identifier
        label: Human-readable label
        goals: List of primary user goals
        proficiency_level: User expertise level
        session_style: Typical interaction pattern
        attention_biases: Signal kind → weight multiplier map
    """

    model_config = {"frozen": True}

    id: str
    label: str
    goals: list[str] = Field(default_factory=list)
    proficiency_level: str = "intermediate"  # novice, intermediate, expert
    session_style: str = "deep_work"  # glance, deep_work
    attention_biases: dict[str, float] = Field(default_factory=dict)

    @field_validator("proficiency_level")
    @classmethod
    def validate_proficiency_level(cls, v: str) -> str:
        """Validate proficiency level is one of allowed values."""
        if v not in ("novice", "intermediate", "expert"):
            raise ValueError(f"proficiency_level must be novice/intermediate/expert, got: {v}")
        return v

    @field_validator("session_style")
    @classmethod
    def validate_session_style(cls, v: str) -> str:
        """Validate session style is one of allowed values."""
        if v not in ("glance", "deep_work"):
            raise ValueError(f"session_style must be glance/deep_work, got: {v}")
        return v


class Stage(StrEnum):
    """
    Named layout stages with specific compositional rules.

    Each stage defines a specific way to organize attention signals
    into a coherent UI structure. Stages are like theater stages -
    they provide a layout where your UI components perform.

    Available stages:
    - FOCUS_METRIC: Spotlight stage - one hero KPI with supporting context
    - SCANNER_TABLE: Open stage - data-heavy table with filters
    - DUAL_PANE_FLOW: Split stage - list on one side, detail on the other
    - MONITOR_WALL: Gallery stage - multiple displays arranged in grid
    - COMMAND_CENTER: Control room stage - dense expert interface
    """

    FOCUS_METRIC = "focus_metric"  # Single dominant KPI/metric
    SCANNER_TABLE = "scanner_table"  # Table-centric with filters
    DUAL_PANE_FLOW = "dual_pane_flow"  # List + detail master-detail
    MONITOR_WALL = "monitor_wall"  # Multiple moderate-importance signals
    COMMAND_CENTER = "command_center"  # Dense, expert-focused dashboard


# Backward compatibility alias
LayoutArchetype = Stage


class LayoutSurface(BaseModel):
    """
    Named region within a layout where signals are rendered.

    Surfaces are the building blocks of layout stages. Each surface
    has a specific purpose and capacity constraints.

    Attributes:
        id: Surface identifier (e.g., "primary", "sidebar", "toolbar")
        stage: Parent stage
        capacity: Maximum attention weight this surface can hold
        priority: Surface priority for signal allocation
        assigned_signals: List of signal IDs assigned to this surface
        constraints: Surface-specific constraints
    """

    model_config = {"frozen": True}

    id: str
    stage: Stage
    capacity: float = Field(default=1.0, ge=0.0)
    priority: int = Field(default=1, ge=1)
    assigned_signals: list[str] = Field(default_factory=list)
    constraints: dict[str, Any] = Field(default_factory=dict)


class LayoutPlan(BaseModel):
    """
    Deterministic output of the layout engine.

    The layout plan specifies exactly how a workspace should be rendered,
    including which stage to use, where each signal appears, and
    any warnings about over-budget situations.

    Attributes:
        workspace_id: Source workspace identifier
        persona_id: Target persona identifier (if persona-specific)
        stage: Selected layout stage
        surfaces: List of surfaces with assigned signals
        over_budget_signals: Signal IDs that couldn't fit
        warnings: Layout warnings (e.g., attention budget exceeded)
        metadata: Additional metadata for debugging/logging
    """

    model_config = {"frozen": True}

    workspace_id: str
    persona_id: str | None = None
    stage: Stage
    surfaces: list[LayoutSurface] = Field(default_factory=list)
    over_budget_signals: list[str] = Field(default_factory=list)
    warnings: list[str] = Field(default_factory=list)
    metadata: dict[str, Any] = Field(default_factory=dict)


class UXLayouts(BaseModel):
    """
    Container for UX semantic layout specifications.

    Holds workspace layouts and persona definitions for the layout engine.

    Attributes:
        workspaces: List of workspace layout specifications
        personas: List of persona layout specifications
    """

    model_config = {"frozen": True}

    workspaces: list[WorkspaceLayout] = Field(default_factory=list)
    personas: list[PersonaLayout] = Field(default_factory=list)
