"""Trigger domain entities and value objects.

Define trigger signals, decisions, and actions for meeting detection.
"""

import time
from dataclasses import dataclass, field
from enum import Enum


class TriggerSource(Enum):
    """Source of a trigger signal."""

    AUDIO_ACTIVITY = "audio_activity"
    FOREGROUND_APP = "foreground_app"
    CALENDAR = "calendar"  # Deferred - optional connector


class TriggerAction(Enum):
    """Action determined by trigger evaluation."""

    from noteflow.config.constants import TRIGGER_ACTION_IGNORE

    IGNORE = TRIGGER_ACTION_IGNORE  # Confidence < 0.40
    NOTIFY = "notify"  # Confidence 0.40-0.79
    AUTO_START = "auto_start"  # Confidence >= 0.80 (if enabled)


@dataclass(frozen=True)
class TriggerSignal:
    """A signal from a single trigger source.

    Attributes:
        source: The source that generated this signal.
        weight: Confidence contribution (0.0-1.0).
        app_name: For foreground app signals, the detected app name.
        timestamp: When the signal was generated (monotonic time).
    """

    source: TriggerSource
    weight: float
    app_name: str | None = None
    timestamp: float = field(default_factory=time.monotonic)

    def __post_init__(self) -> None:
        """Validate weight is in valid range."""
        if not 0.0 <= self.weight <= 1.0:
            msg = f"Weight must be 0.0-1.0, got {self.weight}"
            raise ValueError(msg)


@dataclass(frozen=True)
class TriggerDecision:
    """Result of trigger evaluation.

    Attributes:
        action: The determined action (ignore, notify, auto_start).
        confidence: Total confidence score from all signals.
        signals: The signals that contributed to this decision.
        timestamp: When the decision was made (monotonic time).
    """

    action: TriggerAction
    confidence: float
    signals: tuple[TriggerSignal, ...]
    timestamp: float = field(default_factory=time.monotonic)

    @property
    def primary_signal(self) -> TriggerSignal | None:
        """Get the signal with highest weight contribution."""
        return max(self.signals, key=lambda s: s.weight) if self.signals else None

    @property
    def detected_app(self) -> str | None:
        """Get the detected app name from the first signal that has one."""
        return next(
            (signal.app_name for signal in self.signals if signal.app_name), None
        )
