"""
Build the messages list for the Bedrock/Anthropic API from chat history.
Also gathers attachment context for persistent file awareness.
"""

from sqlalchemy.orm import Session
from backend.models import Chat, Message, ChatAttachment

MAX_CONTEXT_CHARS = 400_000
MAX_MESSAGES = 80
MAX_ATTACHMENT_CONTEXT_CHARS = 200_000


def build_messages(chat: Chat, db: Session) -> list[dict]:
    rows: list[Message] = (
        db.query(Message)
        .filter(Message.chat_id == chat.id)
        .order_by(Message.created_at.desc())
        .limit(MAX_MESSAGES)
        .all()
    )
    rows.reverse()

    if not rows:
        return []

    total_chars = sum(len(m.content or "") for m in rows)
    idx = 0
    while total_chars > MAX_CONTEXT_CHARS and idx < len(rows) - 2:
        total_chars -= len(rows[idx].content or "")
        idx += 1

    trimmed = rows[idx:]

    while trimmed and trimmed[0].role != "user":
        trimmed = trimmed[1:]

    result: list[dict] = []
    for m in trimmed:
        content = m.content or ""
        if not content.strip():
            continue
        role = m.role
        if role not in ("user", "assistant"):
            continue
        if result and result[-1]["role"] == role:
            result[-1]["content"] += "\n" + content
        else:
            result.append({"role": role, "content": content})

    return result


def gather_attachment_context(chat_id: str, db: Session) -> str | None:
    """
    Collect text extracts from ALL attachments in a chat.
    This ensures uploaded files remain "visible" to the AI
    throughout the entire conversation, not just in the message
    where they were uploaded.
    """
    attachments = (
        db.query(ChatAttachment)
        .filter(ChatAttachment.chat_id == chat_id)
        .order_by(ChatAttachment.created_at)
        .all()
    )

    if not attachments:
        return None

    parts = []
    total_chars = 0

    for att in attachments:
        if att.file_type in ("image",):
            # Images: just note they exist (can't include binary in text)
            entry = f"[Uploaded Image: {att.original_filename} ({att.file_size} bytes)]"
        elif att.file_type in ("video",):
            entry = f"[Uploaded Video: {att.original_filename} ({att.file_size} bytes)]"
        elif att.text_extract:
            # Text files and PDFs: include full content
            text = att.text_extract
            remaining = MAX_ATTACHMENT_CONTEXT_CHARS - total_chars
            if remaining <= 0:
                parts.append(f"[{att.original_filename}: content truncated — context limit reached]")
                continue
            if len(text) > remaining:
                text = text[:remaining] + "\n... [truncated]"
            entry = (
                f"━━━ {att.original_filename} ({att.file_type}, {att.file_size} bytes) ━━━\n"
                f"{text}\n"
                f"━━━ end of {att.original_filename} ━━━"
            )
        else:
            entry = f"[Uploaded {att.file_type}: {att.original_filename} ({att.file_size} bytes) — no text extracted]"

        parts.append(entry)
        total_chars += len(entry)

    return "\n\n".join(parts) if parts else None