"""Saved filters routes — CRUD for reusable filter criteria."""

from __future__ import annotations

import uuid
from typing import Any

from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
from pydantic import BaseModel, Field
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.db import get_db
from app.deps import get_current_user, require_permission
from app.models.saved_filter import SavedFilter

router = APIRouter(prefix="/api/v1/saved-filters", tags=["saved-filters"])

VALID_ENTITY_TYPES = {"contacts", "mail", "calendar", "dms"}


class SavedFilterCreate(BaseModel):
    """Schema for creating a saved filter."""
    name: str = Field(..., min_length=1, max_length=100)
    entity_type: str = Field(..., pattern="^(contacts|mail|calendar|dms)$")
    filter_criteria: dict[str, Any] = Field(default_factory=dict)


class SavedFilterUpdate(BaseModel):
    """Schema for updating a saved filter."""
    name: str | None = Field(default=None, min_length=1, max_length=100)
    filter_criteria: dict[str, Any] | None = None


def _filter_to_dict(f: SavedFilter) -> dict[str, Any]:
    return {
        "id": str(f.id),
        "name": f.name,
        "entity_type": f.entity_type,
        "filter_criteria": f.filter_criteria,
        "user_id": str(f.user_id),
        "created_at": f.created_at.isoformat() if f.created_at else None,
        "updated_at": f.updated_at.isoformat() if f.updated_at else None,
    }


@router.get("", dependencies=[Depends(require_permission("contacts:read"))])
async def list_saved_filters(
    entity_type: str | None = Query(None, pattern="^(contacts|mail|calendar|dms)$"),
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """List saved filters for the current user, optionally filtered by entity_type."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])

    query = select(SavedFilter).where(
        SavedFilter.tenant_id == tenant_id,
        SavedFilter.user_id == user_id,
        SavedFilter.deleted_at.is_(None),
    )
    if entity_type:
        query = query.where(SavedFilter.entity_type == entity_type)
    query = query.order_by(SavedFilter.name)

    result = await db.execute(query)
    filters = result.scalars().all()
    return [_filter_to_dict(f) for f in filters]


@router.post("", status_code=status.HTTP_201_CREATED, dependencies=[Depends(require_permission("contacts:read"))])
async def create_saved_filter(
    body: SavedFilterCreate,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Create a new saved filter for the current user."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])

    # Check uniqueness within user+entity
    existing = await db.execute(
        select(SavedFilter).where(
            SavedFilter.tenant_id == tenant_id,
            SavedFilter.user_id == user_id,
            SavedFilter.entity_type == body.entity_type,
            SavedFilter.name == body.name,
            SavedFilter.deleted_at.is_(None),
        )
    )
    if existing.scalar_one_or_none() is not None:
        raise HTTPException(409, detail={"detail": "Filter name already exists", "code": "duplicate"})

    saved = SavedFilter(
        tenant_id=tenant_id,
        user_id=user_id,
        name=body.name,
        entity_type=body.entity_type,
        filter_criteria=body.filter_criteria,
    )
    db.add(saved)
    await db.flush()
    return _filter_to_dict(saved)


@router.delete("/{filter_id}", status_code=status.HTTP_204_NO_CONTENT, dependencies=[Depends(require_permission("contacts:read"))])
async def delete_saved_filter(
    filter_id: str,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """Delete a saved filter (soft-delete)."""
    tenant_id = uuid.UUID(current_user["tenant_id"])
    user_id = uuid.UUID(current_user["user_id"])

    try:
        fid = uuid.UUID(filter_id)
    except (ValueError, TypeError):
        raise HTTPException(400, detail={"detail": "Invalid filter_id", "code": "invalid_id"}) from None

    result = await db.execute(
        select(SavedFilter).where(
            SavedFilter.id == fid,
            SavedFilter.tenant_id == tenant_id,
            SavedFilter.user_id == user_id,
            SavedFilter.deleted_at.is_(None),
        )
    )
    saved = result.scalar_one_or_none()
    if saved is None:
        raise HTTPException(404, detail={"detail": "Saved filter not found", "code": "not_found"})

    from datetime import datetime, timezone
    saved.deleted_at = datetime.now(timezone.utc)
    await db.flush()
    return Response(status_code=status.HTTP_204_NO_CONTENT)
