import logging
from datetime import datetime, timezone
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from devplacepy.database import get_table, db
from devplacepy.attachments import get_attachments_batch
from devplacepy.templating import templates, clear_unread_cache
from devplacepy.utils import generate_uid, require_user, time_ago, create_mention_notifications
from devplacepy.seo import base_seo_context

logger = logging.getLogger(__name__)
router = APIRouter()


def get_conversations(user_uid: str):
    messages_table = get_table("messages")
    raw = (
        list(messages_table.find(sender_uid=user_uid)) +
        list(messages_table.find(receiver_uid=user_uid))
    )
    seen = set()
    all_messages = []
    for m in raw:
        if m["uid"] not in seen:
            seen.add(m["uid"])
            all_messages.append(m)

    conversation_map = {}
    other_uids = set()
    for msg in all_messages:
        other_uid = msg["receiver_uid"] if msg["sender_uid"] == user_uid else msg["sender_uid"]
        other_uids.add(other_uid)
        if other_uid not in conversation_map or msg["created_at"] > conversation_map[other_uid]["last_message_at"]:
            conversation_map[other_uid] = {
                "other_user": None,
                "last_message": msg["content"],
                "last_message_at": msg["created_at"],
                "unread": msg["receiver_uid"] == user_uid and not msg["read"],
            }

    if other_uids:
        from devplacepy.database import get_users_by_uids
        users_map = get_users_by_uids(list(other_uids))
        for uid, conv in conversation_map.items():
            conv["other_user"] = users_map.get(uid)

    conversations = sorted(
        conversation_map.values(),
        key=lambda c: c["last_message_at"],
        reverse=True,
    )
    return conversations


def get_conversation_messages(user_uid: str, other_uid: str):
    messages_table = get_table("messages")
    raw = (
        list(messages_table.find(sender_uid=user_uid, receiver_uid=other_uid)) +
        list(messages_table.find(sender_uid=other_uid, receiver_uid=user_uid))
    )
    seen = set()
    msgs = []
    for m in raw:
        if m["uid"] not in seen:
            seen.add(m["uid"])
            msgs.append(m)
    msgs.sort(key=lambda m: m["created_at"])

    for msg in msgs:
        if msg["receiver_uid"] == user_uid and not msg["read"]:
            messages_table.update({"id": msg["id"], "read": True}, ["id"])

    from devplacepy.database import get_users_by_uids
    user_ids = list({m["sender_uid"] for m in msgs} | {other_uid})
    users_map = get_users_by_uids(user_ids)
    other_user = users_map.get(other_uid)

    result = []
    msg_uids = [m["uid"] for m in msgs]
    attachments_map = get_attachments_batch("message", msg_uids) if msg_uids else {}
    for m in msgs:
        result.append({
            "message": m,
            "sender": users_map.get(m["sender_uid"]),
            "is_mine": m["sender_uid"] == user_uid,
            "time_ago": time_ago(m["created_at"]),
            "attachments": attachments_map.get(m["uid"], []),
        })
    return result, other_user


@router.get("", response_class=HTMLResponse)
async def messages_page(request: Request, with_uid: str = None, search: str = ""):
    user = require_user(request)
    conversations = get_conversations(user["uid"])

    if search:
        users_table = get_table("users")
        found = users_table.find_one(username=search)
        if found:
            with_uid = found["uid"]

    current_conversation = None
    messages = []
    other_user = None
    if with_uid:
        messages, other_user = get_conversation_messages(user["uid"], with_uid)
        current_conversation = with_uid

    seo_ctx = base_seo_context(
        request,
        title="Messages",
        robots="noindex,nofollow",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Messages", "url": "/messages"},
        ],
    )
    return templates.TemplateResponse(request, "messages.html", {
        **seo_ctx,
        "request": request,
        "user": user,
        "conversations": conversations,
        "messages": messages,
        "other_user": other_user,
        "current_conversation": current_conversation,
        "search": search,
    })


@router.get("/search")
async def search_users(request: Request, q: str = ""):
    user = require_user(request)
    if not q or len(q) < 1:
        return JSONResponse({"results": []})
    if "users" in db.tables:
        rows = db.query(
            "SELECT uid, username FROM users WHERE username LIKE :q AND uid != :me LIMIT 10",
            q=f"%{q}%", me=user["uid"],
        )
        results = [{"uid": r["uid"], "username": r["username"]} for r in rows]
    else:
        results = []
    return JSONResponse({"results": results})


@router.post("/send")
async def send_message(request: Request):
    user = require_user(request)
    form = await request.form()
    content = form.get("content", "").strip()
    receiver_uid = form.get("receiver_uid", "")

    if content and receiver_uid:
        messages_table = get_table("messages")
        msg_uid = generate_uid()
        messages_table.insert({
            "uid": msg_uid,
            "sender_uid": user["uid"],
            "receiver_uid": receiver_uid,
            "content": content,
            "read": False,
            "created_at": datetime.now(timezone.utc).isoformat(),
        })

        attachment_uids = form.getlist("attachment_uids") if hasattr(form, "getlist") else []

        from devplacepy.attachments import link_attachments
        link_attachments(attachment_uids, "message", msg_uid)

        if user["uid"] != receiver_uid:
            notifications = get_table("notifications")
            notifications.insert({
                "uid": generate_uid(),
                "user_uid": receiver_uid,
                "type": "message",
                "message": f"{user['username']} sent you a message",
                "related_uid": user["uid"],
                "read": False,
                "created_at": datetime.now(timezone.utc).isoformat(),
            })
            clear_unread_cache(receiver_uid)

        create_mention_notifications(content, user["uid"], f"/messages?with_uid={receiver_uid}")

        logger.info(f"Message {msg_uid} sent from {user['username']} to {receiver_uid}")
        return RedirectResponse(url=f"/messages?with_uid={receiver_uid}", status_code=302)
