"""BAN YARO — Direktnachrichten"""
import logging
import os
import uuid
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from pydantic import BaseModel
from database import db
from auth import get_current_user

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

MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
CHAT_DIR  = os.path.join(MEDIA_DIR, "chat")
ALLOWED_IMAGE_TYPES = {"image/jpeg", "image/png", "image/gif", "image/webp"}
MAX_UPLOAD_BYTES    = 10 * 1024 * 1024  # 10 MB
ONLINE_MINUTES      = 3


def _conv_key(a: int, b: int):
    """Normalisiert Konversations-User-IDs: user_a < user_b."""
    return (min(a, b), max(a, b))


@router.get("/conversations")
async def list_conversations(user=Depends(get_current_user)):
    uid = user["id"]
    online_cutoff = (datetime.utcnow() - timedelta(minutes=ONLINE_MINUTES)).isoformat()
    with db() as conn:
        rows = conn.execute("""
            SELECT c.id, c.last_msg_at,
                   CASE WHEN c.user_a_id=? THEN c.user_b_id ELSE c.user_a_id END AS partner_id,
                   CASE WHEN c.user_a_id=? THEN ub.name    ELSE ua.name    END AS partner_name,
                   CASE WHEN c.user_a_id=? THEN ub.last_seen ELSE ua.last_seen END AS partner_last_seen,
                   (SELECT text FROM direct_messages
                    WHERE conversation_id=c.id AND is_deleted=0
                    ORDER BY created_at DESC LIMIT 1) AS last_text,
                   (SELECT COUNT(*) FROM direct_messages
                    WHERE conversation_id=c.id
                      AND sender_id != ?
                      AND is_deleted=0
                      AND created_at > COALESCE(
                            CASE WHEN c.user_a_id=? THEN c.a_read_at ELSE c.b_read_at END,
                            '1970-01-01'
                          )
                   ) AS unread_count
            FROM conversations c
            JOIN users ua ON ua.id=c.user_a_id
            JOIN users ub ON ub.id=c.user_b_id
            WHERE c.user_a_id=? OR c.user_b_id=?
            ORDER BY COALESCE(c.last_msg_at, c.created_at) DESC
        """, (uid, uid, uid, uid, uid, uid, uid)).fetchall()
    result = []
    for r in rows:
        d = dict(r)
        last_seen = d.get("partner_last_seen")
        d["partner_online"] = bool(last_seen and last_seen >= online_cutoff)
        result.append(d)
    return result


class StartConvModel(BaseModel):
    partner_id: int


@router.post("/conversations", status_code=201)
async def start_conversation(data: StartConvModel, user=Depends(get_current_user)):
    uid = user["id"]
    if uid == data.partner_id:
        raise HTTPException(400, "Du kannst dir selbst keine Nachrichten schicken.")

    a, b = _conv_key(uid, data.partner_id)
    with db() as conn:
        f = conn.execute("""
            SELECT 1 FROM friendships
            WHERE ((requester_id=? AND addressee_id=?) OR (requester_id=? AND addressee_id=?))
              AND status='accepted'
        """, (uid, data.partner_id, data.partner_id, uid)).fetchone()
        if not f:
            raise HTTPException(403, "Ihr seid noch keine Freunde.")

        existing = conn.execute(
            "SELECT id FROM conversations WHERE user_a_id=? AND user_b_id=?", (a, b)
        ).fetchone()
        if existing:
            return {"conversation_id": existing["id"]}

        cur = conn.execute(
            "INSERT INTO conversations (user_a_id, user_b_id) VALUES (?,?)", (a, b)
        )
        return {"conversation_id": cur.lastrowid}


@router.get("/conversations/{conv_id}")
async def get_messages(conv_id: int, offset: int = 0, limit: int = 50,
                       user=Depends(get_current_user)):
    uid = user["id"]
    online_cutoff = (datetime.utcnow() - timedelta(minutes=ONLINE_MINUTES)).isoformat()
    now_iso = datetime.utcnow().isoformat()
    with db() as conn:
        conv = conn.execute(
            "SELECT * FROM conversations WHERE id=? AND (user_a_id=? OR user_b_id=?)",
            (conv_id, uid, uid)
        ).fetchone()
        if not conv:
            raise HTTPException(404, "Konversation nicht gefunden.")

        partner_id = conv["user_b_id"] if conv["user_a_id"] == uid else conv["user_a_id"]
        partner = conn.execute(
            "SELECT name, last_seen FROM users WHERE id=?", (partner_id,)
        ).fetchone()

        # Ungelesene Nachrichten des Partners als gelesen markieren
        conn.execute("""
            UPDATE direct_messages
               SET read_at=?
             WHERE conversation_id=? AND sender_id!=? AND read_at IS NULL
        """, (now_iso, conv_id, uid))

        msgs = conn.execute("""
            SELECT m.id, m.sender_id, m.text, m.is_deleted, m.created_at,
                   m.media_url, m.media_type, m.read_at,
                   u.name AS sender_name
            FROM direct_messages m
            JOIN users u ON u.id=m.sender_id
            WHERE m.conversation_id=?
            ORDER BY m.created_at ASC
            LIMIT ? OFFSET ?
        """, (conv_id, limit, offset)).fetchall()

    partner_last_seen = partner["last_seen"] if partner else None
    partner_online = bool(partner_last_seen and partner_last_seen >= online_cutoff)

    return {
        "conversation_id": conv_id,
        "partner_id":      partner_id,
        "partner_name":    partner["name"] if partner else "Unbekannt",
        "partner_online":  partner_online,
        "messages":        [dict(m) for m in msgs],
    }


class SendMsgModel(BaseModel):
    text: str


@router.post("/conversations/{conv_id}/messages", status_code=201)
async def send_message(conv_id: int, data: SendMsgModel, user=Depends(get_current_user)):
    uid = user["id"]
    text = data.text.strip()
    if not text:
        raise HTTPException(400, "Nachricht darf nicht leer sein.")
    if len(text) > 2000:
        raise HTTPException(400, "Nachricht zu lang (max. 2000 Zeichen).")

    with db() as conn:
        conv = conn.execute(
            "SELECT * FROM conversations WHERE id=? AND (user_a_id=? OR user_b_id=?)",
            (conv_id, uid, uid)
        ).fetchone()
        if not conv:
            raise HTTPException(404, "Konversation nicht gefunden.")

        partner_id = conv["user_b_id"] if conv["user_a_id"] == uid else conv["user_a_id"]

        cur = conn.execute("""
            INSERT INTO direct_messages (conversation_id, sender_id, text) VALUES (?,?,?)
        """, (conv_id, uid, text))
        msg_id = cur.lastrowid

        conn.execute(
            "UPDATE conversations SET last_msg_at=datetime('now') WHERE id=?",
            (conv_id,)
        )

    try:
        from routes.push import send_push_to_user
        preview = text[:100] + ("…" if len(text) > 100 else "")
        send_push_to_user(partner_id, {
            "title": f"Nachricht von {user['name']}",
            "body":  preview,
            "type":  "chat_message",
            "tag":   f"chat-{conv_id}",
            "data":  {"page": "chat", "conversation_id": conv_id},
        })
    except Exception:
        pass

    return {"id": msg_id, "ok": True}


@router.post("/conversations/{conv_id}/upload", status_code=201)
async def upload_photo(conv_id: int, file: UploadFile = File(...),
                       user=Depends(get_current_user)):
    uid = user["id"]
    if file.content_type not in ALLOWED_IMAGE_TYPES:
        raise HTTPException(400, "Nur JPEG, PNG, GIF und WebP erlaubt.")

    data = await file.read()
    if len(data) > MAX_UPLOAD_BYTES:
        raise HTTPException(400, "Datei zu groß (max. 10 MB).")

    os.makedirs(CHAT_DIR, exist_ok=True)
    ext      = os.path.splitext(file.filename or "")[1] or ".jpg"
    filename = f"{uuid.uuid4().hex}{ext}"
    path     = os.path.join(CHAT_DIR, filename)
    with open(path, "wb") as f:
        f.write(data)
    media_url  = f"/media/chat/{filename}"
    media_type = file.content_type

    with db() as conn:
        conv = conn.execute(
            "SELECT * FROM conversations WHERE id=? AND (user_a_id=? OR user_b_id=?)",
            (conv_id, uid, uid)
        ).fetchone()
        if not conv:
            raise HTTPException(404, "Konversation nicht gefunden.")

        partner_id = conv["user_b_id"] if conv["user_a_id"] == uid else conv["user_a_id"]

        cur = conn.execute("""
            INSERT INTO direct_messages (conversation_id, sender_id, text, media_url, media_type)
            VALUES (?,?,?,?,?)
        """, (conv_id, uid, "", media_url, media_type))
        msg_id = cur.lastrowid

        conn.execute(
            "UPDATE conversations SET last_msg_at=datetime('now') WHERE id=?",
            (conv_id,)
        )

    try:
        from routes.push import send_push_to_user
        send_push_to_user(partner_id, {
            "title": f"Foto von {user['name']}",
            "body":  "hat dir ein Foto geschickt",
            "type":  "chat_message",
            "tag":   f"chat-{conv_id}",
            "data":  {"page": "chat", "conversation_id": conv_id},
        })
    except Exception:
        pass

    return {"id": msg_id, "media_url": media_url, "media_type": media_type, "ok": True}


@router.post("/heartbeat")
async def heartbeat(user=Depends(get_current_user)):
    uid     = user["id"]
    now_iso = datetime.utcnow().isoformat()
    with db() as conn:
        conn.execute("UPDATE users SET last_seen=? WHERE id=?", (now_iso, uid))
    return {"ok": True}


@router.post("/conversations/{conv_id}/read")
async def mark_read(conv_id: int, user=Depends(get_current_user)):
    uid = user["id"]
    with db() as conn:
        conv = conn.execute(
            "SELECT * FROM conversations WHERE id=? AND (user_a_id=? OR user_b_id=?)",
            (conv_id, uid, uid)
        ).fetchone()
        if not conv:
            raise HTTPException(404)
        field = "a_read_at" if conv["user_a_id"] == uid else "b_read_at"
        conn.execute(
            f"UPDATE conversations SET {field}=datetime('now') WHERE id=?",
            (conv_id,)
        )
    return {"ok": True}


@router.delete("/messages/{msg_id}")
async def delete_message(msg_id: int, user=Depends(get_current_user)):
    uid = user["id"]
    with db() as conn:
        msg = conn.execute(
            "SELECT id FROM direct_messages WHERE id=? AND sender_id=?", (msg_id, uid)
        ).fetchone()
        if not msg:
            raise HTTPException(404, "Nachricht nicht gefunden.")
        conn.execute(
            "UPDATE direct_messages SET is_deleted=1, text='[gelöscht]' WHERE id=?",
            (msg_id,)
        )
    return {"ok": True}
