"""
Messenger API - Conversation, Message, Group, Template & Stats Routes.

Conversations CRUD, message send/read, groups, templates, stats.
"""

import uuid
from datetime import datetime
from typing import List, Optional

from fastapi import APIRouter, HTTPException, Query

from .models import (
    Conversation,
    Group,
    GroupCreate,
    Message,
    MessageBase,
)
from .helpers import (
    DATA_DIR,
    DEFAULT_TEMPLATES,
    get_contacts,
    get_conversations,
    save_conversations,
    get_messages,
    save_messages,
    get_groups,
    save_groups,
    load_json,
    save_json,
)

router = APIRouter(tags=["Messenger"])


# ==========================================
# GROUPS ENDPOINTS
# ==========================================

@router.get("/groups", response_model=List[Group])
async def list_groups():
    """Listet alle Gruppen auf."""
    return get_groups()


@router.post("/groups", response_model=Group)
async def create_group(group: GroupCreate):
    """Erstellt eine neue Gruppe."""
    groups = get_groups()

    now = datetime.utcnow().isoformat()
    new_group = {
        "id": str(uuid.uuid4()),
        "created_at": now,
        "updated_at": now,
        **group.dict()
    }

    groups.append(new_group)
    save_groups(groups)

    return new_group


@router.put("/groups/{group_id}/members")
async def update_group_members(group_id: str, member_ids: List[str]):
    """Aktualisiert die Mitglieder einer Gruppe."""
    groups = get_groups()
    group_idx = next((i for i, g in enumerate(groups) if g["id"] == group_id), None)

    if group_idx is None:
        raise HTTPException(status_code=404, detail="Gruppe nicht gefunden")

    groups[group_idx]["member_ids"] = member_ids
    groups[group_idx]["updated_at"] = datetime.utcnow().isoformat()

    save_groups(groups)
    return groups[group_idx]


@router.delete("/groups/{group_id}")
async def delete_group(group_id: str):
    """Loescht eine Gruppe."""
    groups = get_groups()
    groups = [g for g in groups if g["id"] != group_id]
    save_groups(groups)

    return {"status": "deleted", "id": group_id}


# ==========================================
# CONVERSATIONS ENDPOINTS
# ==========================================

@router.get("/conversations", response_model=List[Conversation])
async def list_conversations():
    """Listet alle Konversationen auf."""
    conversations = get_conversations()
    messages = get_messages()

    # Unread count und letzte Nachricht hinzufuegen
    for conv in conversations:
        conv_messages = [m for m in messages if m.get("conversation_id") == conv["id"]]
        conv["unread_count"] = len([m for m in conv_messages if not m.get("read") and m.get("sender_id") != "self"])

        if conv_messages:
            last_msg = max(conv_messages, key=lambda m: m.get("timestamp", ""))
            conv["last_message"] = last_msg.get("content", "")[:50]
            conv["last_message_time"] = last_msg.get("timestamp")

    # Nach letzter Nachricht sortieren
    conversations.sort(key=lambda c: c.get("last_message_time") or "", reverse=True)

    return conversations


@router.post("/conversations", response_model=Conversation)
async def create_conversation(contact_id: Optional[str] = None, group_id: Optional[str] = None):
    """
    Erstellt eine neue Konversation.
    Entweder mit einem Kontakt (1:1) oder einer Gruppe.
    """
    conversations = get_conversations()

    if not contact_id and not group_id:
        raise HTTPException(status_code=400, detail="Entweder contact_id oder group_id erforderlich")

    # Pruefen ob Konversation bereits existiert
    if contact_id:
        existing = next((c for c in conversations
                        if not c.get("is_group") and contact_id in c.get("participant_ids", [])), None)
        if existing:
            return existing

    now = datetime.utcnow().isoformat()

    if group_id:
        groups = get_groups()
        group = next((g for g in groups if g["id"] == group_id), None)
        if not group:
            raise HTTPException(status_code=404, detail="Gruppe nicht gefunden")

        new_conv = {
            "id": str(uuid.uuid4()),
            "name": group.get("name"),
            "is_group": True,
            "participant_ids": group.get("member_ids", []),
            "group_id": group_id,
            "created_at": now,
            "updated_at": now,
            "last_message": None,
            "last_message_time": None,
            "unread_count": 0
        }
    else:
        contacts = get_contacts()
        contact = next((c for c in contacts if c["id"] == contact_id), None)
        if not contact:
            raise HTTPException(status_code=404, detail="Kontakt nicht gefunden")

        new_conv = {
            "id": str(uuid.uuid4()),
            "name": contact.get("name"),
            "is_group": False,
            "participant_ids": [contact_id],
            "group_id": None,
            "created_at": now,
            "updated_at": now,
            "last_message": None,
            "last_message_time": None,
            "unread_count": 0
        }

    conversations.append(new_conv)
    save_conversations(conversations)

    return new_conv


@router.get("/conversations/{conversation_id}", response_model=Conversation)
async def get_conversation(conversation_id: str):
    """Ruft eine Konversation ab."""
    conversations = get_conversations()
    conv = next((c for c in conversations if c["id"] == conversation_id), None)

    if not conv:
        raise HTTPException(status_code=404, detail="Konversation nicht gefunden")

    return conv


@router.delete("/conversations/{conversation_id}")
async def delete_conversation(conversation_id: str):
    """Loescht eine Konversation und alle zugehoerigen Nachrichten."""
    conversations = get_conversations()
    conversations = [c for c in conversations if c["id"] != conversation_id]
    save_conversations(conversations)

    messages = get_messages()
    messages = [m for m in messages if m.get("conversation_id") != conversation_id]
    save_messages(messages)

    return {"status": "deleted", "id": conversation_id}


# ==========================================
# MESSAGES ENDPOINTS
# ==========================================

@router.get("/conversations/{conversation_id}/messages", response_model=List[Message])
async def list_messages(
    conversation_id: str,
    limit: int = Query(50, ge=1, le=200),
    before: Optional[str] = Query(None, description="Load messages before this timestamp")
):
    """Ruft Nachrichten einer Konversation ab."""
    messages = get_messages()
    conv_messages = [m for m in messages if m.get("conversation_id") == conversation_id]

    if before:
        conv_messages = [m for m in conv_messages if m.get("timestamp", "") < before]

    # Nach Zeit sortieren (neueste zuletzt)
    conv_messages.sort(key=lambda m: m.get("timestamp", ""))

    return conv_messages[-limit:]


@router.post("/conversations/{conversation_id}/messages", response_model=Message)
async def send_message(conversation_id: str, message: MessageBase):
    """
    Sendet eine Nachricht in einer Konversation.

    Wenn send_email=True und der Kontakt eine Email-Adresse hat,
    wird die Nachricht auch per Email versendet.
    """
    conversations = get_conversations()
    conv = next((c for c in conversations if c["id"] == conversation_id), None)

    if not conv:
        raise HTTPException(status_code=404, detail="Konversation nicht gefunden")

    now = datetime.utcnow().isoformat()

    new_message = {
        "id": str(uuid.uuid4()),
        "conversation_id": conversation_id,
        "sender_id": "self",
        "timestamp": now,
        "read": True,
        "read_at": now,
        "email_sent": False,
        "email_sent_at": None,
        "email_error": None,
        **message.dict()
    }

    # Email-Versand wenn gewuenscht
    if message.send_email and not conv.get("is_group"):
        # Kontakt laden
        participant_ids = conv.get("participant_ids", [])
        if participant_ids:
            contacts = get_contacts()
            contact = next((c for c in contacts if c["id"] == participant_ids[0]), None)

            if contact and contact.get("email"):
                try:
                    from services.email import email_service

                    result = email_service.send_messenger_notification(
                        to_email=contact["email"],
                        to_name=contact.get("name", ""),
                        sender_name="BreakPilot Lehrer",
                        message_content=message.content
                    )

                    if result.success:
                        new_message["email_sent"] = True
                        new_message["email_sent_at"] = result.sent_at
                    else:
                        new_message["email_error"] = result.error

                except Exception as e:
                    new_message["email_error"] = str(e)

    messages = get_messages()
    messages.append(new_message)
    save_messages(messages)

    # Konversation aktualisieren
    conv_idx = next(i for i, c in enumerate(conversations) if c["id"] == conversation_id)
    conversations[conv_idx]["last_message"] = message.content[:50]
    conversations[conv_idx]["last_message_time"] = now
    conversations[conv_idx]["updated_at"] = now
    save_conversations(conversations)

    return new_message


@router.put("/messages/{message_id}/read")
async def mark_message_read(message_id: str):
    """Markiert eine Nachricht als gelesen."""
    messages = get_messages()
    msg_idx = next((i for i, m in enumerate(messages) if m["id"] == message_id), None)

    if msg_idx is None:
        raise HTTPException(status_code=404, detail="Nachricht nicht gefunden")

    messages[msg_idx]["read"] = True
    messages[msg_idx]["read_at"] = datetime.utcnow().isoformat()
    save_messages(messages)

    return {"status": "read", "id": message_id}


@router.put("/conversations/{conversation_id}/read-all")
async def mark_all_messages_read(conversation_id: str):
    """Markiert alle Nachrichten einer Konversation als gelesen."""
    messages = get_messages()
    now = datetime.utcnow().isoformat()

    for msg in messages:
        if msg.get("conversation_id") == conversation_id and not msg.get("read"):
            msg["read"] = True
            msg["read_at"] = now

    save_messages(messages)

    return {"status": "all_read", "conversation_id": conversation_id}


# ==========================================
# TEMPLATES ENDPOINTS
# ==========================================

@router.get("/templates")
async def list_templates():
    """Listet alle Nachrichtenvorlagen auf."""
    templates_file = DATA_DIR / "templates.json"
    if templates_file.exists():
        templates = load_json(templates_file)
    else:
        templates = DEFAULT_TEMPLATES
        save_json(templates_file, templates)

    return templates


@router.post("/templates")
async def create_template(name: str, content: str, category: str = "custom"):
    """Erstellt eine neue Vorlage."""
    templates_file = DATA_DIR / "templates.json"
    templates = load_json(templates_file) if templates_file.exists() else DEFAULT_TEMPLATES.copy()

    new_template = {
        "id": str(uuid.uuid4()),
        "name": name,
        "content": content,
        "category": category
    }

    templates.append(new_template)
    save_json(templates_file, templates)

    return new_template


@router.delete("/templates/{template_id}")
async def delete_template(template_id: str):
    """Loescht eine Vorlage."""
    templates_file = DATA_DIR / "templates.json"
    templates = load_json(templates_file) if templates_file.exists() else DEFAULT_TEMPLATES.copy()

    templates = [t for t in templates if t["id"] != template_id]
    save_json(templates_file, templates)

    return {"status": "deleted", "id": template_id}


# ==========================================
# STATS ENDPOINT
# ==========================================

@router.get("/stats")
async def get_messenger_stats():
    """Gibt Statistiken zum Messenger zurueck."""
    contacts = get_contacts()
    conversations = get_conversations()
    messages = get_messages()
    groups = get_groups()

    unread_total = sum(1 for m in messages if not m.get("read") and m.get("sender_id") != "self")

    return {
        "total_contacts": len(contacts),
        "total_groups": len(groups),
        "total_conversations": len(conversations),
        "total_messages": len(messages),
        "unread_messages": unread_total,
        "contacts_by_role": {
            role: len([c for c in contacts if c.get("role") == role])
            for role in set(c.get("role", "parent") for c in contacts)
        }
    }
