"""
Chat attachment upload, serve, and delete routes.
"""

import os
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query, Request
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session

from backend.database import get_db
from backend.models import User, Chat, ChatAttachment
from backend.auth import get_current_user, decode_token
from backend.services import attachment_service
from backend.config import MAX_ATTACHMENT_BYTES

router = APIRouter()


def _get_user_from_request(request: Request, db: Session, token_param: Optional[str] = None) -> User:
    """
    Resolve user from either:
    1. Authorization: Bearer <token> header
    2. ?token=<token> query parameter (for img/video tags)
    """
    raw_token = None

    # Try header first
    auth_header = request.headers.get("authorization", "")
    if auth_header.startswith("Bearer "):
        raw_token = auth_header[7:]

    # Fall back to query param
    if not raw_token and token_param:
        raw_token = token_param

    if not raw_token:
        raise HTTPException(401, "Authentication required")

    payload = decode_token(raw_token)
    user = db.query(User).filter(User.id == payload["sub"]).first()
    if not user or not user.is_active:
        raise HTTPException(401, "User not found or inactive")
    return user


@router.post("/chats/{chat_id}/attachments")
async def upload_attachments(
    chat_id: str,
    files: list[UploadFile] = File(...),
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Upload one or more files as chat attachments. Returns attachment metadata."""
    chat = db.query(Chat).filter(Chat.id == chat_id, Chat.user_id == user.id).first()
    if not chat:
        raise HTTPException(404, "Chat not found")

    results = []
    for file in files:
        filename = file.filename or "file"
        try:
            content = await file.read()
            if len(content) > MAX_ATTACHMENT_BYTES:
                results.append({
                    "error": f"File too large: {filename} ({len(content) // 1024 // 1024}MB). Max {MAX_ATTACHMENT_BYTES // 1024 // 1024}MB.",
                })
                continue

            meta = attachment_service.save_attachment(
                chat_id=chat_id,
                filename=filename,
                content=content,
                content_type=file.content_type,
            )

            att = ChatAttachment(
                id=meta["id"],
                chat_id=chat_id,
                filename=meta["filename"],
                original_filename=meta["original_filename"],
                mime_type=meta["mime_type"],
                file_type=meta["file_type"],
                file_size=meta["file_size"],
                storage_path=meta["storage_path"],
                text_extract=meta.get("text_extract"),
            )
            db.add(att)
            db.commit()
            db.refresh(att)

            results.append(_att_dict(att))

        except Exception as e:
            results.append({"error": f"Failed to upload {filename}: {str(e)}"})

    return {"attachments": results}


@router.get("/attachments/{attachment_id}/file")
def serve_attachment(
    attachment_id: str,
    request: Request,
    token: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """
    Serve an attachment file.
    Supports both Bearer header auth and ?token= query param
    (needed for <img> tags that can't send headers).
    """
    user = _get_user_from_request(request, db, token)

    att = db.query(ChatAttachment).filter(ChatAttachment.id == attachment_id).first()
    if not att:
        raise HTTPException(404, "Attachment not found")

    chat = db.query(Chat).filter(Chat.id == att.chat_id).first()
    if not chat or (chat.user_id != user.id and user.role != "superadmin"):
        raise HTTPException(403, "Access denied")

    if not os.path.exists(att.storage_path):
        raise HTTPException(404, "File not found on disk")

    return FileResponse(
        att.storage_path,
        media_type=att.mime_type,
        filename=att.original_filename,
    )


@router.delete("/attachments/{attachment_id}")
def delete_attachment(
    attachment_id: str,
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Delete a single attachment."""
    att = db.query(ChatAttachment).filter(ChatAttachment.id == attachment_id).first()
    if not att:
        raise HTTPException(404)

    chat = db.query(Chat).filter(Chat.id == att.chat_id).first()
    if not chat or (chat.user_id != user.id and user.role != "superadmin"):
        raise HTTPException(403)

    attachment_service.delete_attachment_file(att.storage_path)
    db.delete(att)
    db.commit()
    return {"ok": True}


def _att_dict(att: ChatAttachment) -> dict:
    return {
        "id": att.id,
        "chat_id": att.chat_id,
        "message_id": att.message_id,
        "filename": att.filename,
        "original_filename": att.original_filename,
        "mime_type": att.mime_type,
        "file_type": att.file_type,
        "file_size": att.file_size,
        "created_at": str(att.created_at),
    }