from __future__ import annotations

from typing import Any

from core.protocol import (
    Attachment,
    IncomingCallback,
    IncomingCommand,
    IncomingEvent,
    IncomingMessage,
)

PLATFORM = "matrix"


def extract_attachments(event: Any) -> list[Attachment]:
    source = getattr(event, "source", {}) or {}
    content = source.get("content", {}) or getattr(event, "content", {}) or {}
    msgtype = getattr(event, "msgtype", None)
    if msgtype is None:
        msgtype = content.get("msgtype")
    url = content.get("url") or getattr(event, "url", None)
    filename = content.get("body") or getattr(event, "body", None)
    mime_type = content.get("mimetype") or getattr(event, "mimetype", None)
    if mime_type is None:
        info = content.get("info") or {}
        if isinstance(info, dict):
            mime_type = info.get("mimetype")

    if msgtype == "m.image":
        return [
            Attachment(
                type="image",
                url=url,
                filename=filename,
                mime_type=mime_type,
            )
        ]
    if msgtype == "m.file":
        return [
            Attachment(
                type="document",
                url=url,
                filename=filename,
                mime_type=mime_type,
            )
        ]
    if msgtype == "m.audio":
        return [
            Attachment(
                type="audio",
                url=url,
                filename=filename,
                mime_type=mime_type,
            )
        ]
    if msgtype == "m.video":
        return [
            Attachment(
                type="video",
                url=url,
                filename=filename,
                mime_type=mime_type,
            )
        ]
    return []


def from_command(body: str, sender: str, chat_id: str, room_id: str | None = None) -> IncomingEvent:
    raw = body.lstrip("!").strip()
    parts = raw.split()
    command = parts[0].lower() if parts else ""
    args = parts[1:]

    if command in {"yes", "no"}:
        action = "confirm" if command == "yes" else "cancel"
        return IncomingCallback(
            user_id=sender,
            platform=PLATFORM,
            chat_id=chat_id,
            action=action,
            payload={
                "source": "command",
                "command": command,
                **({"room_id": room_id} if room_id is not None else {}),
            },
        )

    if command == "list" and not args:
        return IncomingCommand(
            user_id=sender,
            platform=PLATFORM,
            chat_id=chat_id,
            command="matrix_list_attachments",
            args=[],
        )

    if command == "remove" and len(args) == 1:
        return IncomingCommand(
            user_id=sender,
            platform=PLATFORM,
            chat_id=chat_id,
            command="matrix_remove_attachment",
            args=[args[0]],
        )

    aliases = {
        "skills": "settings_skills",
        "connectors": "settings_connectors",
        "soul": "settings_soul",
        "safety": "settings_safety",
        "plan": "settings_plan",
        "status": "settings_status",
        "whoami": "settings_whoami",
    }
    command = aliases.get(command, command)
    return IncomingCommand(
        user_id=sender,
        platform=PLATFORM,
        chat_id=chat_id,
        command=command,
        args=args,
    )


def from_room_event(event: Any, room_id: str, chat_id: str) -> IncomingEvent | None:
    body = (getattr(event, "body", None) or "").strip()
    sender = getattr(event, "sender", "")
    if body.startswith("!"):
        return from_command(body, sender=sender, chat_id=chat_id, room_id=room_id)
    return IncomingMessage(
        user_id=sender,
        platform=PLATFORM,
        chat_id=chat_id,
        text=body,
        attachments=extract_attachments(event),
        reply_to=getattr(event, "replyto_event_id", None),
    )
