"""
Intake — Multi-channel message normalization.

Converts raw channel-specific messages into a unified Signal dataclass
that flows through the NeuralClaw cognitive pipeline.
"""

from __future__ import annotations

import time
import uuid
from dataclasses import dataclass, field
from enum import Enum, auto
from typing import Any

from neuralclaw.bus.neural_bus import EventType, NeuralBus


# ---------------------------------------------------------------------------
# Signal model
# ---------------------------------------------------------------------------

class ChannelType(Enum):
    """Supported channel types."""
    CLI = auto()
    TELEGRAM = auto()
    DISCORD = auto()
    WHATSAPP = auto()
    SLACK = auto()
    SIGNAL = auto()
    WEB = auto()


@dataclass
class Signal:
    """
    Unified, channel-agnostic message representation.

    Every incoming message — regardless of source — is normalized into
    a Signal before entering the cognitive pipeline.
    """

    id: str = field(default_factory=lambda: uuid.uuid4().hex[:12])
    content: str = ""
    author_id: str = ""
    author_name: str = ""
    channel_type: ChannelType = ChannelType.CLI
    channel_id: str = ""
    timestamp: float = field(default_factory=time.time)
    reply_to: str | None = None
    media: list[dict[str, Any]] = field(default_factory=list)
    metadata: dict[str, Any] = field(default_factory=dict)

    # Enriched by perception pipeline
    intent: str | None = None
    threat_score: float = 0.0
    is_blocked: bool = False
    context: dict[str, Any] = field(default_factory=dict)


# ---------------------------------------------------------------------------
# Perception Intake
# ---------------------------------------------------------------------------

class PerceptionIntake:
    """
    First stage of perception — normalizes raw channel messages into Signals
    and publishes SIGNAL_RECEIVED to the neural bus.
    """

    def __init__(self, bus: NeuralBus) -> None:
        self._bus = bus

    async def process(
        self,
        content: str,
        author_id: str = "user",
        author_name: str = "User",
        channel_type: ChannelType = ChannelType.CLI,
        channel_id: str = "cli",
        reply_to: str | None = None,
        media: list[dict[str, Any]] | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> Signal:
        """Normalize a raw message into a Signal and publish it."""

        # Clean content
        cleaned = self._normalize_text(content)

        signal = Signal(
            content=cleaned,
            author_id=author_id,
            author_name=author_name,
            channel_type=channel_type,
            channel_id=channel_id,
            reply_to=reply_to,
            media=media or [],
            metadata=metadata or {},
        )

        # Publish to bus
        await self._bus.publish(
            EventType.SIGNAL_RECEIVED,
            {
                "signal_id": signal.id,
                "source": channel_type.name.lower(),
                "author": author_name,
                "content": cleaned,
            },
            source="perception.intake",
        )

        return signal

    def _normalize_text(self, text: str) -> str:
        """Strip extraneous whitespace and formatting artifacts."""
        # Remove zero-width chars, normalize whitespace
        text = text.strip()
        # Collapse multiple newlines
        lines = [line.strip() for line in text.splitlines()]
        return "\n".join(line for line in lines if line)
