from datetime import datetime
from typing import Any, Dict, List, Optional

from config import POSTGRES_CONNECTION_STRING


async def delete_conversation_by_chat_id(chat_id: str) -> Dict[str, Any]:
    """Delete wx-agent LangGraph checkpoint state for one chat_id."""
    chat_id = str(chat_id or "").strip()
    if not chat_id:
        raise ValueError("chat_id is empty")

    counts = {
        "checkpoint_writes": 0,
        "checkpoint_blobs": 0,
        "checkpoints": 0,
    }
    async with await _connect_pool() as pool:
        async with pool.connection() as conn:
            async with conn.cursor() as cur:
                await _delete_checkpoint_threads(cur, chat_id, counts)
    return {"success": True, "chat_id": chat_id, "deleted": counts}


async def delete_conversations_by_time(
    before: Optional[datetime] = None,
    after: Optional[datetime] = None,
) -> Dict[str, Any]:
    """Delete LangGraph checkpoint state whose checkpoint timestamp falls in a time range."""
    if before is None and after is None:
        raise ValueError("before or after is required")

    where_parts = []
    params: List[Any] = []
    if before is not None:
        where_parts.append("(checkpoint->>'ts')::timestamptz < %s")
        params.append(before)
    if after is not None:
        where_parts.append("(checkpoint->>'ts')::timestamptz >= %s")
        params.append(after)
    where_sql = " AND ".join(where_parts)

    counts = {
        "checkpoint_writes": 0,
        "checkpoint_blobs": 0,
        "checkpoints": 0,
    }
    deleted_thread_ids: List[str] = []

    async with await _connect_pool() as pool:
        async with pool.connection() as conn:
            async with conn.cursor() as cur:
                await cur.execute(
                    f"SELECT DISTINCT thread_id FROM checkpoints WHERE {where_sql}",
                    params,
                )
                deleted_thread_ids = [str(row[0]) for row in await cur.fetchall() if row and row[0]]

                for thread_id in deleted_thread_ids:
                    await _delete_exact_thread(cur, thread_id, counts)

    return {
        "success": True,
        "before": before.isoformat() if before else "",
        "after": after.isoformat() if after else "",
        "thread_count": len(deleted_thread_ids),
        "thread_ids": deleted_thread_ids,
        "deleted": counts,
    }


async def _delete_checkpoint_threads(cur, chat_id: str, counts: Dict[str, int]) -> None:
    thread_like = f"{chat_id}:%"
    await cur.execute(
        "DELETE FROM checkpoint_writes WHERE thread_id = %s OR thread_id LIKE %s",
        (chat_id, thread_like),
    )
    counts["checkpoint_writes"] += cur.rowcount or 0
    await cur.execute(
        "DELETE FROM checkpoint_blobs WHERE thread_id = %s OR thread_id LIKE %s",
        (chat_id, thread_like),
    )
    counts["checkpoint_blobs"] += cur.rowcount or 0
    await cur.execute(
        "DELETE FROM checkpoints WHERE thread_id = %s OR thread_id LIKE %s",
        (chat_id, thread_like),
    )
    counts["checkpoints"] += cur.rowcount or 0


async def _delete_exact_thread(cur, thread_id: str, counts: Dict[str, int]) -> None:
    await cur.execute("DELETE FROM checkpoint_writes WHERE thread_id = %s", (thread_id,))
    counts["checkpoint_writes"] += cur.rowcount or 0
    await cur.execute("DELETE FROM checkpoint_blobs WHERE thread_id = %s", (thread_id,))
    counts["checkpoint_blobs"] += cur.rowcount or 0
    await cur.execute("DELETE FROM checkpoints WHERE thread_id = %s", (thread_id,))
    counts["checkpoints"] += cur.rowcount or 0


async def _connect_pool():
    from psycopg_pool import AsyncConnectionPool

    return AsyncConnectionPool(
        POSTGRES_CONNECTION_STRING,
        kwargs={"autocommit": True},
    )
