"""Knowledge Vault routes."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session

from app.core.db import get_db
from app.schemas.vault import (
    VaultIndexRequest,
    VaultIndexResponse,
    VaultPathRead,
    VaultPathToggleRequest,
    VaultPathsResponse,
    VaultRegisterRequest,
    VaultSearchHitRead,
    VaultSearchResponse,
    VaultStatusResponse,
)
from app.services import vault

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


@router.post("/register", response_model=VaultPathRead, status_code=status.HTTP_201_CREATED)
def register_vault_path(
    payload: VaultRegisterRequest,
    db: Session = Depends(get_db),
) -> VaultPathRead:
    """Register one local folder for indexing."""
    try:
        item = vault.register_vault_path(db=db, raw_path=payload.path)
    except vault.VaultError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

    for path_item in vault.list_vault_paths(db=db):
        if int(path_item["id"]) == int(item.id):
            return VaultPathRead.model_validate(path_item)

    return VaultPathRead.model_validate({"id": item.id, "path": item.path, "enabled": item.enabled, "created_at": item.created_at})


@router.get("/paths", response_model=VaultPathsResponse)
def list_vault_paths(db: Session = Depends(get_db)) -> VaultPathsResponse:
    """List registered vault paths and counters."""
    items = vault.list_vault_paths(db=db)
    run_status = vault.get_last_status()
    return VaultPathsResponse(
        paths=[VaultPathRead.model_validate(item) for item in items],
        is_running=bool(run_status.get("is_running")),
        last_run_at=run_status.get("last_run_at"),
        last_finished_at=run_status.get("last_finished_at"),
        last_stats=run_status.get("last_stats"),
        last_errors=list(run_status.get("last_errors") or []),
    )


@router.post("/paths/{path_id}/enabled", response_model=VaultPathRead)
def set_vault_path_enabled(
    path_id: int,
    payload: VaultPathToggleRequest,
    db: Session = Depends(get_db),
) -> VaultPathRead:
    """Enable or disable a registered vault path."""
    try:
        item = vault.set_vault_path_enabled(db=db, path_id=path_id, enabled=payload.enabled)
    except LookupError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc

    return VaultPathRead.model_validate(item)


@router.post("/index", response_model=VaultIndexResponse)
def run_vault_index(
    payload: VaultIndexRequest | None = None,
    db: Session = Depends(get_db),
) -> VaultIndexResponse:
    """Run incremental index for one path or all enabled paths."""
    path_id = payload.path_id if payload else None
    try:
        summary = vault.index_vault(db=db, path_id=path_id)
    except vault.VaultIndexInProgressError as exc:
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(exc)) from exc
    except vault.VaultError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
    except LookupError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc

    return VaultIndexResponse.model_validate(summary)


@router.get("/status", response_model=VaultStatusResponse)
def get_vault_status(db: Session = Depends(get_db)) -> VaultStatusResponse:
    """Return vault counts and latest index status."""
    return VaultStatusResponse.model_validate(vault.status_summary(db=db))


@router.get("/search", response_model=VaultSearchResponse)
def search_vault(
    q: str = Query(..., min_length=1),
    limit: int = Query(default=10, ge=1, le=50),
    db: Session = Depends(get_db),
) -> VaultSearchResponse:
    """Search indexed note chunks using FTS5."""
    try:
        hits = vault.search_vault(db=db, query=q, limit=limit)
    except vault.VaultNotIndexedError as exc:
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(exc)) from exc
    except vault.VaultError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

    return VaultSearchResponse(
        query=q,
        results=[
            VaultSearchHitRead(
                file_path=item.file_path,
                chunk_id=item.chunk_id,
                snippet=item.snippet,
                rank=item.rank,
            )
            for item in hits
        ],
    )
