"""AI Assistant plugin routes — providers, models, presets, agents,
sessions, messages, tools, and streaming chat.
"""

from __future__ import annotations

import uuid

from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
from fastapi.responses import FileResponse, StreamingResponse
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.db import get_db, set_tenant_context
from app.deps import get_current_user, require_permission
from app.plugins.builtins.ai_assistant.models import (
    AIAgent,
    AIChatAttachment,
    AIChatFolder,
    AIChatSession,
    AIModel,
    AIPreset,
    AIProvider,
)
from app.plugins.builtins.ai_assistant.schemas import (
    AIAgentCreate,
    AIAgentUpdate,
    AIModelCreate,
    AIModelUpdate,
    AIPresetCreate,
    AIPresetUpdate,
    AIProviderCreate,
    AIProviderUpdate,
    ChatAttachmentResponse,
    ChatFolderCreate,
    ChatFolderUpdate,
    ChatFolderResponse,
    ChatSendRequest,
    ChatSessionCreate,
    ChatSessionUpdate,
)
from app.plugins.builtins.ai_assistant.services import (
    agent_to_response,
    attachment_to_response,
    folder_to_response,
    get_agent_by_id,
    get_default_agent,
    get_preset_by_id,
    get_provider_by_id,
    get_session_by_id,
    get_session_messages,
    message_to_response,
    model_to_response,
    preset_to_response,
    provider_to_response,
    session_to_response,
    stream_chat,
)
from app.plugins.builtins.ai_assistant.tool_registry import get_tool_registry

router = APIRouter(prefix="/api/v1/ai", tags=["ai-assistant"])


# ─── Providers ───

@router.get("/providers", dependencies=[Depends(require_permission("ai:config"))])
async def list_providers(
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIProvider).where(AIProvider.tenant_id == tenant_id)
    )
    providers = list(result.scalars().all())
    return [provider_to_response(p) for p in providers]


@router.post("/providers", dependencies=[Depends(require_permission("ai:config"))])
async def create_provider(
    data: AIProviderCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    await set_tenant_context(db, tenant_id)

    # If is_default, unset other defaults
    if data.is_default:
        existing = await db.execute(
            select(AIProvider)
            .where(AIProvider.tenant_id == tenant_id)
            .where(AIProvider.is_default == True)
        )
        for p in existing.scalars().all():
            p.is_default = False

    provider = AIProvider(
        name=data.name,
        provider_type=data.provider_type,
        api_key=data.api_key,
        base_url=data.base_url,
        is_active=data.is_active,
        is_default=data.is_default,
        config=data.config,
        tenant_id=tenant_id,
    )
    db.add(provider)
    await db.commit()
    await db.refresh(provider)
    return provider_to_response(provider)


@router.put("/providers/{provider_id}", dependencies=[Depends(require_permission("ai:config"))])
async def update_provider(
    provider_id: str,
    data: AIProviderUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    provider = await get_provider_by_id(db, uuid.UUID(provider_id), tenant_id)
    if not provider:
        raise HTTPException(status_code=404, detail="Provider not found")

    if data.is_default:
        existing = await db.execute(
            select(AIProvider)
            .where(AIProvider.tenant_id == tenant_id)
            .where(AIProvider.is_default == True)
            .where(AIProvider.id != provider.id)
        )
        for p in existing.scalars().all():
            p.is_default = False

    for field, val in data.model_dump(exclude_unset=True).items():
        setattr(provider, field, val)
    await db.commit()
    await db.refresh(provider)
    return provider_to_response(provider)


@router.delete("/providers/{provider_id}", dependencies=[Depends(require_permission("ai:config"))])
async def delete_provider(
    provider_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    provider = await get_provider_by_id(db, uuid.UUID(provider_id), tenant_id)
    if not provider:
        raise HTTPException(status_code=404, detail="Provider not found")
    await db.delete(provider)
    await db.commit()
    return {"ok": True}


# ─── Models ───

@router.get("/models", dependencies=[Depends(require_permission("ai:config"))])
async def list_models(
    provider_id: str | None = Query(None),
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    stmt = select(AIModel).where(AIModel.tenant_id == tenant_id)
    if provider_id:
        stmt = stmt.where(AIModel.provider_id == uuid.UUID(provider_id))
    result = await db.execute(stmt)
    models = list(result.scalars().all())
    return [model_to_response(m) for m in models]


@router.post("/models", dependencies=[Depends(require_permission("ai:config"))])
async def create_model(
    data: AIModelCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    await set_tenant_context(db, tenant_id)

    model = AIModel(
        provider_id=uuid.UUID(data.provider_id),
        model_id=data.model_id,
        display_name=data.display_name,
        context_window=data.context_window,
        supports_tools=data.supports_tools,
        supports_streaming=data.supports_streaming,
        is_active=data.is_active,
        config=data.config,
        tenant_id=tenant_id,
    )
    db.add(model)
    await db.commit()
    await db.refresh(model)
    return model_to_response(model)


@router.put("/models/{model_id}", dependencies=[Depends(require_permission("ai:config"))])
async def update_model(
    model_id: str,
    data: AIModelUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIModel)
        .where(AIModel.id == uuid.UUID(model_id))
        .where(AIModel.tenant_id == tenant_id)
    )
    model = result.scalar_one_or_none()
    if not model:
        raise HTTPException(status_code=404, detail="Model not found")

    for field, val in data.model_dump(exclude_unset=True).items():
        setattr(model, field, val)
    await db.commit()
    await db.refresh(model)
    return model_to_response(model)


@router.delete("/models/{model_id}", dependencies=[Depends(require_permission("ai:config"))])
async def delete_model(
    model_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIModel)
        .where(AIModel.id == uuid.UUID(model_id))
        .where(AIModel.tenant_id == tenant_id)
    )
    model = result.scalar_one_or_none()
    if not model:
        raise HTTPException(status_code=404, detail="Model not found")
    await db.delete(model)
    await db.commit()
    return {"ok": True}


# ─── Presets ───

@router.get("/presets", dependencies=[Depends(require_permission("ai:config"))])
async def list_presets(
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIPreset).where(AIPreset.tenant_id == tenant_id)
    )
    presets = list(result.scalars().all())
    return [preset_to_response(p) for p in presets]


@router.post("/presets", dependencies=[Depends(require_permission("ai:config"))])
async def create_preset(
    data: AIPresetCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    await set_tenant_context(db, tenant_id)

    preset = AIPreset(
        name=data.name,
        model_id=data.model_id,
        provider_id=uuid.UUID(data.provider_id) if data.provider_id else None,
        temperature=data.temperature,
        max_tokens=data.max_tokens,
        top_p=data.top_p,
        system_prompt=data.system_prompt,
        config=data.config,
        is_active=data.is_active,
        tenant_id=tenant_id,
    )
    db.add(preset)
    await db.commit()
    await db.refresh(preset)
    return preset_to_response(preset)


@router.put("/presets/{preset_id}", dependencies=[Depends(require_permission("ai:config"))])
async def update_preset(
    preset_id: str,
    data: AIPresetUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    preset = await get_preset_by_id(db, uuid.UUID(preset_id), tenant_id)
    if not preset:
        raise HTTPException(status_code=404, detail="Preset not found")

    update_data = data.model_dump(exclude_unset=True)
    if "provider_id" in update_data and update_data["provider_id"]:
        update_data["provider_id"] = uuid.UUID(update_data["provider_id"])
    for field, val in update_data.items():
        setattr(preset, field, val)
    await db.commit()
    await db.refresh(preset)
    return preset_to_response(preset)


@router.delete("/presets/{preset_id}", dependencies=[Depends(require_permission("ai:config"))])
async def delete_preset(
    preset_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    preset = await get_preset_by_id(db, uuid.UUID(preset_id), tenant_id)
    if not preset:
        raise HTTPException(status_code=404, detail="Preset not found")
    await db.delete(preset)
    await db.commit()
    return {"ok": True}


# ─── Agents ───

@router.get("/agents", dependencies=[Depends(require_permission("ai:read"))])
async def list_agents(
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIAgent).where(AIAgent.tenant_id == tenant_id)
    )
    agents = list(result.scalars().all())
    return [agent_to_response(a) for a in agents]


@router.post("/agents", dependencies=[Depends(require_permission("ai:agents"))])
async def create_agent(
    data: AIAgentCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    await set_tenant_context(db, tenant_id)

    agent = AIAgent(
        name=data.name,
        description=data.description,
        system_prompt=data.system_prompt,
        preset_id=uuid.UUID(data.preset_id) if data.preset_id else None,
        tool_ids=data.tool_ids,
        is_active=data.is_active,
        config=data.config,
        tenant_id=tenant_id,
    )
    db.add(agent)
    await db.commit()
    await db.refresh(agent)
    return agent_to_response(agent)


@router.put("/agents/{agent_id}", dependencies=[Depends(require_permission("ai:agents"))])
async def update_agent(
    agent_id: str,
    data: AIAgentUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    agent = await get_agent_by_id(db, uuid.UUID(agent_id), tenant_id)
    if not agent:
        raise HTTPException(status_code=404, detail="Agent not found")

    update_data = data.model_dump(exclude_unset=True)
    if "preset_id" in update_data and update_data["preset_id"]:
        update_data["preset_id"] = uuid.UUID(update_data["preset_id"])
    for field, val in update_data.items():
        setattr(agent, field, val)
    await db.commit()
    await db.refresh(agent)
    return agent_to_response(agent)


@router.delete("/agents/{agent_id}", dependencies=[Depends(require_permission("ai:agents"))])
async def delete_agent(
    agent_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    agent = await get_agent_by_id(db, uuid.UUID(agent_id), tenant_id)
    if not agent:
        raise HTTPException(status_code=404, detail="Agent not found")
    if agent.is_default:
        raise HTTPException(status_code=400, detail="Cannot delete default agent")
    await db.delete(agent)
    await db.commit()
    return {"ok": True}


# ─── Tools ───

@router.get("/tools", dependencies=[Depends(require_permission("ai:read"))])
async def list_tools(
    current_user: dict = Depends(get_current_user),
):
    registry = get_tool_registry()
    return registry.list_for_api()


# ─── Chat Sessions ───

@router.get("/sessions", dependencies=[Depends(require_permission("ai:read"))])
async def list_sessions(
    is_sidebar: bool | None = Query(None),
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    stmt = (
        select(AIChatSession)
        .where(AIChatSession.tenant_id == tenant_id)
        .where(AIChatSession.user_id == user_id)
    )
    if is_sidebar is not None:
        stmt = stmt.where(AIChatSession.is_sidebar == is_sidebar)
    stmt = stmt.order_by(AIChatSession.updated_at.desc())
    result = await db.execute(stmt)
    sessions = list(result.scalars().all())
    return [session_to_response(s) for s in sessions]


@router.post("/sessions", dependencies=[Depends(require_permission("ai:write"))])
async def create_session(
    data: ChatSessionCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    await set_tenant_context(db, tenant_id)

    agent_id = None
    if data.agent_id:
        agent_id = uuid.UUID(data.agent_id)
    elif not data.is_sidebar:
        # Use default agent for non-sidebar sessions
        default_agent = await get_default_agent(db, tenant_id)
        if default_agent:
            agent_id = default_agent.id
    else:
        # Sidebar also gets default agent
        default_agent = await get_default_agent(db, tenant_id)
        if default_agent:
            agent_id = default_agent.id

    folder_id = None
    if data.folder_id:
        folder_id = uuid.UUID(data.folder_id)

    session = AIChatSession(
        user_id=user_id,
        agent_id=agent_id,
        title=data.title,
        is_sidebar=data.is_sidebar,
        folder_id=folder_id,
        tenant_id=tenant_id,
    )
    db.add(session)
    await db.commit()
    await db.refresh(session)
    return session_to_response(session)


@router.put("/sessions/{session_id}", dependencies=[Depends(require_permission("ai:write"))])
async def update_session(
    session_id: str,
    data: ChatSessionUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    update_data = data.model_dump(exclude_unset=True)
    if "agent_id" in update_data and update_data["agent_id"]:
        update_data["agent_id"] = uuid.UUID(update_data["agent_id"])
    if "folder_id" in update_data:
        if update_data["folder_id"]:
            update_data["folder_id"] = uuid.UUID(update_data["folder_id"])
        else:
            update_data["folder_id"] = None
    for field, val in update_data.items():
        setattr(session, field, val)
    await db.commit()
    await db.refresh(session)
    return session_to_response(session)


@router.delete("/sessions/{session_id}", dependencies=[Depends(require_permission("ai:write"))])
async def delete_session(
    session_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")
    await db.delete(session)
    await db.commit()
    return {"ok": True}


# ─── Chat Messages ───

@router.get("/sessions/{session_id}/messages", dependencies=[Depends(require_permission("ai:read"))])
async def list_messages(
    session_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    messages = await get_session_messages(db, session.id, tenant_id)
    return [message_to_response(m) for m in messages]


# ─── Streaming Chat ───

@router.post("/sessions/{session_id}/stream", dependencies=[Depends(require_permission("ai:write"))])
async def chat_stream(
    session_id: str,
    data: ChatSendRequest,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    # Get agent
    agent = None
    if data.agent_id:
        agent = await get_agent_by_id(db, uuid.UUID(data.agent_id), tenant_id)
    elif session.agent_id:
        agent = await get_agent_by_id(db, session.agent_id, tenant_id)
    if not agent:
        agent = await get_default_agent(db, tenant_id)
    if not agent:
        raise HTTPException(status_code=400, detail="No agent available")

    # Build user context for RBAC checks in tools
    user_context = {
        "user_id": current_user["user_id"],
        "tenant_id": current_user["tenant_id"],
        "role": current_user.get("role", ""),
        "permissions": current_user.get("permissions", []),
        "denied_permissions": current_user.get("denied_permissions", []),
        "is_system_admin": current_user.get("is_system_admin", False),
        "field_permissions": current_user.get("field_permissions", {}),
    }

    async def event_stream():
        async for chunk in stream_chat(
            db, session, agent, data.content, user_context, tenant_id
        ):
            yield chunk
        yield "data: [DONE]\n\n"

    return StreamingResponse(
        event_stream(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        },
    )


# ─── Chat Folders ───

@router.get("/folders", dependencies=[Depends(require_permission("ai:read"))])
async def list_folders(
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    result = await db.execute(
        select(AIChatFolder)
        .where(AIChatFolder.tenant_id == tenant_id)
        .where(AIChatFolder.user_id == user_id)
        .order_by(AIChatFolder.name.asc())
    )
    folders = list(result.scalars().all())
    return [folder_to_response(f) for f in folders]


@router.post("/folders", dependencies=[Depends(require_permission("ai:write"))])
async def create_folder(
    data: ChatFolderCreate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    await set_tenant_context(db, tenant_id)

    folder = AIChatFolder(
        name=data.name,
        parent_id=uuid.UUID(data.parent_id) if data.parent_id else None,
        user_id=user_id,
        tenant_id=tenant_id,
    )
    db.add(folder)
    await db.commit()
    await db.refresh(folder)
    return folder_to_response(folder)


@router.put("/folders/{folder_id}", dependencies=[Depends(require_permission("ai:write"))])
async def update_folder(
    folder_id: str,
    data: ChatFolderUpdate,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    result = await db.execute(
        select(AIChatFolder)
        .where(AIChatFolder.id == uuid.UUID(folder_id))
        .where(AIChatFolder.tenant_id == tenant_id)
        .where(AIChatFolder.user_id == user_id)
    )
    folder = result.scalar_one_or_none()
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")

    update_data = data.model_dump(exclude_unset=True)
    if "parent_id" in update_data:
        if update_data["parent_id"]:
            update_data["parent_id"] = uuid.UUID(update_data["parent_id"])
        else:
            update_data["parent_id"] = None
    for field, val in update_data.items():
        setattr(folder, field, val)
    await db.commit()
    await db.refresh(folder)
    return folder_to_response(folder)


@router.delete("/folders/{folder_id}", dependencies=[Depends(require_permission("ai:write"))])
async def delete_folder(
    folder_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    result = await db.execute(
        select(AIChatFolder)
        .where(AIChatFolder.id == uuid.UUID(folder_id))
        .where(AIChatFolder.tenant_id == tenant_id)
        .where(AIChatFolder.user_id == user_id)
    )
    folder = result.scalar_one_or_none()
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")
    await db.delete(folder)
    await db.commit()
    return {"ok": True}


# ─── Attachments ───

import os
from pathlib import Path

ATTACHMENT_DIR = Path(os.environ.get("STORAGE_PATH", "/data/storage")) / "ai_attachments"
MAX_ATTACHMENT_SIZE = 25 * 1024 * 1024  # 25MB


@router.post("/sessions/{session_id}/attachments", dependencies=[Depends(require_permission("ai:write"))])
async def upload_attachment(
    session_id: str,
    file: UploadFile,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    content = await file.read()
    if len(content) > MAX_ATTACHMENT_SIZE:
        raise HTTPException(status_code=413, detail="File too large (max 25MB)")

    ATTACHMENT_DIR.mkdir(parents=True, exist_ok=True)
    file_id = str(uuid.uuid4())
    safe_filename = file.filename or "unnamed"
    storage_path = str(ATTACHMENT_DIR / f"{file_id}_{safe_filename}")
    with open(storage_path, "wb") as f:
        f.write(content)

    attachment = AIChatAttachment(
        session_id=session.id,
        filename=safe_filename,
        mime_type=file.content_type or "application/octet-stream",
        size_bytes=len(content),
        storage_path=storage_path,
        tenant_id=tenant_id,
    )
    db.add(attachment)
    await db.commit()
    await db.refresh(attachment)
    return attachment_to_response(attachment)


@router.get("/sessions/{session_id}/attachments", dependencies=[Depends(require_permission("ai:read"))])
async def list_attachments(
    session_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])
    session = await get_session_by_id(db, uuid.UUID(session_id), user_id, tenant_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    result = await db.execute(
        select(AIChatAttachment)
        .where(AIChatAttachment.session_id == session.id)
        .where(AIChatAttachment.tenant_id == tenant_id)
        .order_by(AIChatAttachment.created_at.asc())
    )
    attachments = list(result.scalars().all())
    return [attachment_to_response(a) for a in attachments]


@router.get("/attachments/{attachment_id}/download", dependencies=[Depends(require_permission("ai:read"))])
async def download_attachment(
    attachment_id: str,
    current_user: dict = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = uuid.UUID(current_user["tenant_id"])
    result = await db.execute(
        select(AIChatAttachment)
        .where(AIChatAttachment.id == uuid.UUID(attachment_id))
        .where(AIChatAttachment.tenant_id == tenant_id)
    )
    attachment = result.scalar_one_or_none()
    if not attachment:
        raise HTTPException(status_code=404, detail="Attachment not found")

    return FileResponse(
        attachment.storage_path,
        filename=attachment.filename,
        media_type=attachment.mime_type,
    )
