"""API вложений M2: изображения задач, в том числе вставка из буфера обмена."""

import shutil
import uuid
from pathlib import Path
from typing import Any, cast

from fastapi import APIRouter, HTTPException, UploadFile
from fastapi.responses import FileResponse
from sqlalchemy import select

from app.config import get_settings
from app.dependencies import DbDep, UserDep
from app.models import Attachment, Task
from app.schemas import AttachmentOut

router = APIRouter(prefix="/api", tags=["attachments"])

ALLOWED_PREFIXES = ("image/",)


def _attachments_dir() -> Path:
    path = Path(get_settings().attachments_path)
    path.mkdir(parents=True, exist_ok=True)
    return path


def _get_task_or_404(db: Any, task_id: int) -> Task:
    task = cast(Task | None, db.get(Task, task_id))
    if task is None:
        raise HTTPException(status_code=404, detail="Task not found")
    return task


def _get_attachment_or_404(db: Any, attachment_id: int) -> Attachment:
    att = cast(Attachment | None, db.get(Attachment, attachment_id))
    if att is None:
        raise HTTPException(status_code=404, detail="Attachment not found")
    return att


@router.post("/tasks/{task_id}/attachments", response_model=list[AttachmentOut])
async def upload_attachments(
    task_id: int, db: DbDep, user: UserDep, files: list[UploadFile]
) -> list[Attachment]:
    """Загрузка файлов (в т.ч. Ctrl+V из буфера — приходит как обычный файл)."""
    _get_task_or_404(db, task_id)
    saved: list[Attachment] = []
    for file in files:
        mime = file.content_type or "application/octet-stream"
        if not mime.startswith(ALLOWED_PREFIXES):
            raise HTTPException(status_code=415, detail=f"Unsupported type: {mime}")
        ext = Path(file.filename or "image").suffix or ".bin"
        stored_name = f"{uuid.uuid4().hex}{ext}"
        target = _attachments_dir() / stored_name
        with target.open("wb") as out:
            shutil.copyfileobj(file.file, out)
        att = Attachment(
            task_id=task_id,
            filename=stored_name,
            original_name=(file.filename or "image")[:255],
            mime=mime,
            size=target.stat().st_size,
        )
        db.add(att)
        saved.append(att)
    db.flush()
    return saved


@router.get("/tasks/{task_id}/attachments", response_model=list[AttachmentOut])
async def list_attachments(task_id: int, db: DbDep, user: UserDep) -> list[Attachment]:
    _get_task_or_404(db, task_id)
    return list(
        db.scalars(
            select(Attachment).where(Attachment.task_id == task_id).order_by(Attachment.id)
        ).all()
    )


@router.get("/attachments/{attachment_id}/file")
async def get_attachment_file(
    attachment_id: int, db: DbDep, user: UserDep
) -> FileResponse:
    att = _get_attachment_or_404(db, attachment_id)
    path = _attachments_dir() / att.filename
    if not path.is_file():
        raise HTTPException(status_code=404, detail="File missing on disk")
    return FileResponse(path, media_type=att.mime)


@router.delete("/attachments/{attachment_id}")
async def delete_attachment(attachment_id: int, db: DbDep, user: UserDep) -> dict[str, bool]:
    att = _get_attachment_or_404(db, attachment_id)
    path = _attachments_dir() / att.filename
    if path.is_file():
        path.unlink()
    db.delete(att)
    return {"ok": True}
