"""Attachment upload + serving (M4) — plan §6.5.

Two read routes: by attachment id (a DB row, created once its owning
comment is posted) and by-path (the raw staged filename, for previewing an
upload that hasn't been linked to a comment yet — ref §3.5's instant
preview). Both funnel through services.attachments.read_upload, the one
traversal guard for serving a file. Sync def (react.md). Auth: the
default-deny middleware gates every route here automatically — no
additional check needed in this file.
"""
from __future__ import annotations

import uuid

from fastapi import APIRouter, Depends, File, UploadFile
from fastapi.responses import FileResponse, JSONResponse
from sqlalchemy.orm import Session

from ..db import get_db
from ..models import Attachment
from ..services import attachments as attachments_service

router = APIRouter()


def _error_response(err: attachments_service.AttachmentError) -> JSONResponse:
    return JSONResponse(
        status_code=err.status_code,
        content={
            "error_code": err.error_code,
            "summary": err.summary,
            "detail": err.detail,
        },
    )


@router.post("/api/attachments")
def upload_attachment(file: UploadFile = File(...)):
    """Stage a pasted image (composer flow, ref §3.5): validate mime/size,
    write it to upload_dir under a fresh UUID name, and hand back its
    identity. No Comment link yet — the composer references this file_path
    when it later POSTs the comment (services.conversation.create_comment)."""
    content = file.file.read()
    try:
        staged = attachments_service.store_upload(file.content_type, content)
    except attachments_service.AttachmentError as err:
        return _error_response(err)
    return staged


@router.get("/api/attachments/{attachment_id}")
def get_attachment(attachment_id: uuid.UUID, db: Session = Depends(get_db)):
    attachment = db.get(Attachment, attachment_id)
    if attachment is None:
        return JSONResponse(
            status_code=404,
            content={
                "error_code": "ATTACHMENT_NOT_FOUND",
                "summary": f"No attachment {attachment_id}",
            },
        )
    try:
        abs_path = attachments_service.read_upload(attachment.file_path)
    except attachments_service.AttachmentError as err:
        return _error_response(err)
    return FileResponse(abs_path, media_type=attachment.mime)


@router.get("/api/attachments/by-path/{file_path}")
def get_attachment_by_path(file_path: str):
    """Pre-link preview: serves a freshly staged upload before any comment
    references it. Same traversal guard as the by-id route above — this one
    matters more, since file_path here is raw client input, not a value
    looked up from a DB row."""
    try:
        abs_path = attachments_service.read_upload(file_path)
    except attachments_service.AttachmentError as err:
        return _error_response(err)
    return FileResponse(abs_path)
