from __future__ import annotations

import uuid
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from db.models import Document, Topic, User
from deps.auth import get_current_user
from deps.db import get_db
from services import classifier, storage

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


class TopicCreate(BaseModel):
    name: str
    description: str = ""
    color: str = "#6366f1"


class TopicUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    color: Optional[str] = None


class SuggestRequest(BaseModel):
    document_id: str


@router.get("")
async def list_topics(
    session: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """List topics visible to the current user: system topics + their own topics.

    D-08 + D-17: namespace-scoped query — returns system topics (user_id IS NULL)
    + the authenticated user's own topics. Never returns other users' topics.
    """
    topics = await storage.load_topics_for_user(session, user_id=current_user.id)
    counts = await storage.topic_doc_counts(session, user_id=current_user.id)
    for t in topics:
        t["doc_count"] = counts.get(t["name"], 0)
    return {"topics": topics}


@router.post("")
async def create_topic(
    body: TopicCreate,
    session: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Create a per-user topic (user_id = current_user.id).

    D-09: regular users can only create topics in their own namespace.
    For system topics (user_id = NULL), use POST /api/admin/topics.
    Deduplication is scoped to the user's namespace.
    """
    topic = await storage.create_topic(
        session, body.name, body.description, body.color, user_id=current_user.id
    )
    topic["doc_count"] = 0
    return topic


@router.patch("/{topic_id}")
async def update_topic(
    topic_id: str,
    body: TopicUpdate,
    session: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Update a user-owned topic.

    D-09: users can only edit their own topics. System topics (user_id IS NULL)
    and other users' topics return 404 (not 403) to avoid information leakage.
    """
    try:
        uid = uuid.UUID(topic_id)
    except ValueError:
        raise HTTPException(404, "Topic not found")

    t = await session.get(Topic, uid)
    if t is None or t.user_id != current_user.id:
        raise HTTPException(404, "Topic not found")

    topic = await storage.update_topic(
        session,
        topic_id,
        name=body.name,
        description=body.description,
        color=body.color,
    )
    if topic is None:
        raise HTTPException(404, "Topic not found")
    counts = await storage.topic_doc_counts(session, user_id=current_user.id)
    topic["doc_count"] = counts.get(topic["name"], 0)
    return topic


@router.delete("/{topic_id}")
async def delete_topic(
    topic_id: str,
    session: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Delete a user-owned topic.

    D-09: users can only delete their own topics. System topics (user_id IS NULL)
    and other users' topics return 404 (not 403) to avoid information leakage.
    """
    try:
        uid = uuid.UUID(topic_id)
    except ValueError:
        raise HTTPException(404, "Topic not found")

    t = await session.get(Topic, uid)
    if t is None or t.user_id != current_user.id:
        raise HTTPException(404, "Topic not found")

    name = await storage.delete_topic(session, topic_id)
    if name is None:
        raise HTTPException(404, "Topic not found")
    return {"success": True, "removed_from_documents": True}


@router.post("/suggest")
async def suggest_topics(
    body: SuggestRequest,
    session: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Suggest topics for a document using AI.

    D-11: classifier uses the user's namespace (system + user topics) for suggestions.
    D-16 / SEC-IDOR: asserts document ownership — cross-user access returns 404
    to prevent document ID enumeration (same pattern as documents router).
    """
    try:
        uid = uuid.UUID(body.document_id)
    except ValueError:
        raise HTTPException(404, "Document not found")

    doc = await session.get(Document, uid)
    if doc is None or doc.user_id != current_user.id:
        raise HTTPException(404, "Document not found")

    try:
        suggestions = await classifier.suggest_topics_for_document(session, body.document_id)
    except Exception as e:
        raise HTTPException(500, f"Suggestion failed: {e}")
    return {"suggested": suggestions}
