"""Game integration configuration data models.

Defines the GameIntegrationConfig dataclass and EventMapping dataclass
for persisting game integration settings (adapter type, event mappings,
per-integration config).
"""

import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, List, Optional


@dataclass
class EventMapping:
    """Maps a standard game event type to a visual effect.

    Attributes:
        event_type: Standard event type from the vocabulary (e.g. "health", "kill").
        effect: Effect name to trigger (e.g. "flash", "pulse", "gradient").
        color: RGB color as [R, G, B] (0-255 each).
        duration_ms: Effect duration in milliseconds.
        intensity: Effect intensity 0.0-1.0.
        priority: Priority for effect stacking (higher wins).
    """

    event_type: str
    effect: str = "flash"
    color: List[int] = field(default_factory=lambda: [255, 0, 0])
    duration_ms: int = 500
    intensity: float = 1.0
    priority: int = 0

    def to_dict(self) -> dict:
        return {
            "event_type": self.event_type,
            "effect": self.effect,
            "color": list(self.color),
            "duration_ms": self.duration_ms,
            "intensity": self.intensity,
            "priority": self.priority,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "EventMapping":
        return cls(
            event_type=data["event_type"],
            effect=data.get("effect", "flash"),
            color=list(data.get("color", [255, 0, 0])),
            duration_ms=data.get("duration_ms", 500),
            intensity=data.get("intensity", 1.0),
            priority=data.get("priority", 0),
        )


@dataclass
class GameIntegrationConfig:
    """Persistent configuration for a game integration.

    Attributes:
        id: Unique identifier (gi_<8hex>).
        name: Human-readable name.
        adapter_type: Registered adapter type string.
        enabled: Whether this integration is active.
        adapter_config: Adapter-specific settings (secrets, mappings, etc.).
        event_mappings: List of event-to-effect mappings.
        created_at: Creation timestamp.
        updated_at: Last modification timestamp.
        description: Optional description.
        tags: User-defined tags.
    """

    id: str
    name: str
    adapter_type: str
    enabled: bool
    adapter_config: dict[str, Any]
    event_mappings: List[EventMapping]
    created_at: datetime
    updated_at: datetime
    description: Optional[str] = None
    tags: List[str] = field(default_factory=list)

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "name": self.name,
            "adapter_type": self.adapter_type,
            "enabled": self.enabled,
            "adapter_config": dict(self.adapter_config),
            "event_mappings": [m.to_dict() for m in self.event_mappings],
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat(),
            "description": self.description,
            "tags": list(self.tags),
        }

    @classmethod
    def from_dict(cls, data: dict) -> "GameIntegrationConfig":
        mappings = [EventMapping.from_dict(m) for m in data.get("event_mappings", [])]
        return cls(
            id=data["id"],
            name=data["name"],
            adapter_type=data["adapter_type"],
            enabled=data.get("enabled", True),
            adapter_config=data.get("adapter_config", {}),
            event_mappings=mappings,
            created_at=(
                datetime.fromisoformat(data["created_at"])
                if isinstance(data.get("created_at"), str)
                else data.get("created_at", datetime.now(timezone.utc))
            ),
            updated_at=(
                datetime.fromisoformat(data["updated_at"])
                if isinstance(data.get("updated_at"), str)
                else data.get("updated_at", datetime.now(timezone.utc))
            ),
            description=data.get("description"),
            tags=data.get("tags", []),
        )

    @staticmethod
    def create_from_kwargs(
        name: str,
        adapter_type: str,
        enabled: bool = True,
        adapter_config: Optional[dict[str, Any]] = None,
        event_mappings: Optional[List[EventMapping]] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> "GameIntegrationConfig":
        """Factory method to create a new config with generated ID and timestamps."""
        now = datetime.now(timezone.utc)
        return GameIntegrationConfig(
            id=f"gi_{uuid.uuid4().hex[:8]}",
            name=name,
            adapter_type=adapter_type,
            enabled=enabled,
            adapter_config=adapter_config or {},
            event_mappings=event_mappings or [],
            created_at=now,
            updated_at=now,
            description=description,
            tags=tags or [],
        )

    def apply_update(
        self,
        name: Optional[str] = None,
        adapter_type: Optional[str] = None,
        enabled: Optional[bool] = None,
        adapter_config: Optional[dict[str, Any]] = None,
        event_mappings: Optional[List[EventMapping]] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> "GameIntegrationConfig":
        """Return a new config with updated fields (immutable update)."""
        return GameIntegrationConfig(
            id=self.id,
            name=name if name is not None else self.name,
            adapter_type=adapter_type if adapter_type is not None else self.adapter_type,
            enabled=enabled if enabled is not None else self.enabled,
            adapter_config=adapter_config if adapter_config is not None else self.adapter_config,
            event_mappings=event_mappings if event_mappings is not None else self.event_mappings,
            created_at=self.created_at,
            updated_at=datetime.now(timezone.utc),
            description=description if description is not None else self.description,
            tags=tags if tags is not None else self.tags,
        )
