"""Saved searches — zapisane słowa kluczowe per urządzenie.

User-report mobilism: sceny słabo opisane → user chce zapisywać często używane
zapytania i szybko je odpalać. Scope po device_id (X-Device-Id), jak reszta stanu.

Endpointy:
  GET    /saved-searches            — lista zapisów tego urządzenia (najnowsze pierwsze)
  POST   /saved-searches            — dodaj {query} (idempotent na device+query)
  DELETE /saved-searches/{id}       — usuń
"""
from __future__ import annotations

import uuid
from datetime import datetime
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, field_validator
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.api.device import get_device_id
from app.auth import require_api_key
from app.db import get_session
from app.models.saved_search import SavedSearch

router = APIRouter(
    prefix="/saved-searches",
    tags=["saved-searches"],
    dependencies=[Depends(require_api_key)],
)

# Limit zapisów per urządzenie — to wygodny skrót, nie nieograniczona kolekcja.
MAX_PER_DEVICE = 50


class SavedSearchOut(BaseModel):
    id: uuid.UUID
    query: str
    created_at: datetime


class SavedSearchIn(BaseModel):
    query: str

    @field_validator("query")
    @classmethod
    def _clean(cls, v: str) -> str:
        v = (v or "").strip()
        if not v:
            raise ValueError("query empty")
        return v[:256]


@router.get("", response_model=list[SavedSearchOut])
def list_saved_searches(
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> list[SavedSearch]:
    rows = session.execute(
        select(SavedSearch)
        .where(SavedSearch.device_id == device_id)
        .order_by(SavedSearch.created_at.desc())
    ).scalars().all()
    return list(rows)


@router.post("", response_model=SavedSearchOut, status_code=status.HTTP_200_OK)
def add_saved_search(
    payload: SavedSearchIn,
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> SavedSearch:
    # Idempotent — ten sam (device, query) zwraca istniejący wiersz.
    existing = session.execute(
        select(SavedSearch).where(
            SavedSearch.device_id == device_id, SavedSearch.query == payload.query
        )
    ).scalar_one_or_none()
    if existing is not None:
        return existing
    count = session.execute(
        select(SavedSearch.id).where(SavedSearch.device_id == device_id)
    ).scalars().all()
    if len(count) >= MAX_PER_DEVICE:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"saved-search limit ({MAX_PER_DEVICE}) reached",
        )
    row = SavedSearch(device_id=device_id, query=payload.query)
    session.add(row)
    session.commit()
    session.refresh(row)
    return row


@router.delete("/{search_id}", status_code=status.HTTP_204_NO_CONTENT)
def remove_saved_search(
    search_id: uuid.UUID,
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> None:
    row = session.get(SavedSearch, search_id)
    # Tylko własne urządzenie może usuwać; cudze/nieistniejące → idempotentny no-op.
    if row is None or row.device_id != device_id:
        return
    session.delete(row)
    session.commit()
