"""
FTS search over photos.search_vector with optional tag/date filters.
"""
import logging
from typing import Optional

from sqlalchemy import select, text
from sqlalchemy.ext.asyncio import AsyncSession

from app.models import Photo

logger = logging.getLogger(__name__)


async def hybrid_search(
    db: AsyncSession,
    q: Optional[str] = None,
    tag_ids: Optional[list[str]] = None,
    date_from: Optional[str] = None,
    date_to: Optional[str] = None,
    limit: int = 50,
    offset: int = 0,
) -> list[dict]:
    """Full-text search using photos.search_vector. No embeddings, no OCR."""
    if q:
        try:
            fts_stmt = text("""
                SELECT id, ts_rank(search_vector, plainto_tsquery('english', :q)) AS rank
                FROM photos
                WHERE search_vector @@ plainto_tsquery('english', :q)
                  AND is_trashed = false
                  AND is_hidden = false
                ORDER BY rank DESC
                LIMIT 500
            """)
            rows = (await db.execute(fts_stmt, {"q": q})).fetchall()
        except Exception as e:
            logger.warning("FTS search failed: %s", e)
            rows = []

        scored = [(pid, float(rank)) for pid, rank in rows]

        if tag_ids:
            from app.models.tags import photo_tags
            photo_ids = [pid for pid, _ in scored]
            if not photo_ids:
                return []
            stmt = select(photo_tags.c.photo_id).where(
                photo_tags.c.photo_id.in_(photo_ids),
                photo_tags.c.tag_id.in_(tag_ids),
            ).distinct()
            valid = {row[0] for row in (await db.execute(stmt)).fetchall()}
            scored = [(pid, s) for pid, s in scored if pid in valid]

        page = scored[offset : offset + limit]
        return [{"photo_id": pid, "score": s} for pid, s in page]

    # No text query — recent photos with tag/date filters.
    if tag_ids:
        from app.models.tags import photo_tags
        sub = select(photo_tags.c.photo_id).where(
            photo_tags.c.tag_id.in_(tag_ids)
        ).distinct().subquery()
        stmt = select(Photo.id).join(sub, Photo.id == sub.c.photo_id)
    else:
        stmt = select(Photo.id)
    stmt = stmt.where(
        Photo.is_discarded.is_(False),
        Photo.is_hidden.is_(False),
    )
    if date_from:
        stmt = stmt.where(Photo.taken_at >= date_from)
    if date_to:
        stmt = stmt.where(Photo.taken_at <= date_to)
    stmt = stmt.order_by(Photo.added_at.desc()).offset(offset).limit(limit)
    rows = (await db.execute(stmt)).fetchall()
    return [{"photo_id": row[0], "score": 0.0} for row in rows]
