import json
import logging
from datetime import datetime, timezone
from typing import Any

from common.mongo_client import mongodb_client, COLLECTION_INBOX, utc_now

logger = logging.getLogger(__name__)


class MongoDBConversationManager:
    """MongoDB-based chat history storage."""

    def __init__(self, collection_name: str = "cuccu_chat_history"):
        self.collection_name = collection_name

    async def initialize_table(self):
        """Ensure indexes exist."""
        try:
            await mongodb_client.db[self.collection_name].create_index(
                [("identity_key", 1), ("timestamp", -1)]
            )
            await mongodb_client.db[self.collection_name].create_index(
                [("identity_key", 1), ("is_human", 1), ("timestamp", -1)]
            )
            logger.info(f"MongoDB collection {self.collection_name} initialized")
        except Exception as e:
            logger.error(f"Error initializing MongoDB collection: {e}")

    async def save_conversation_turn(self, identity_key: str, human_message: str, ai_message: str):
        """Save human and AI messages."""
        try:
            ts = utc_now()
            base_id = int(ts.timestamp() * 1000000)

            docs = [
                {
                    "id": base_id,
                    "identity_key": identity_key,
                    "message": human_message,
                    "is_human": True,
                    "timestamp": ts,
                },
                {
                    "id": base_id + 1,
                    "identity_key": identity_key,
                    "message": ai_message,
                    "is_human": False,
                    "timestamp": ts,
                },
            ]

            await mongodb_client.db[self.collection_name].insert_many(docs)
            logger.debug(f"Saved conversation turn for {identity_key} (MongoDB)")
        except Exception as e:
            logger.error(f"Failed to save conversation (MongoDB): {e}")
            raise

    async def get_chat_history(
        self, identity_key: str, limit: int | None = None, before_id: int | None = None
    ) -> list[dict[str, Any]]:
        """Retrieve chat history."""
        try:
            query = {"identity_key": identity_key}

            if before_id:
                query["id"] = {"$lt": before_id}

            cursor = mongodb_client.db[self.collection_name].find(query).sort("id", -1)

            if limit:
                cursor = cursor.limit(limit)

            docs = await cursor.to_list(length=limit or 100)

            history = []
            for doc in docs:
                message_content = doc["message"]
                is_human = doc["is_human"]

                entry = {
                    "is_human": is_human,
                    "timestamp": doc["timestamp"],
                    "id": doc["id"],
                }

                if is_human:
                    entry["message"] = message_content
                else:
                    try:
                        parsed = json.loads(message_content)
                        entry["message"] = parsed.get("ai_response", message_content)
                        entry["product_ids"] = parsed.get("product_ids", [])
                    except (json.JSONDecodeError, TypeError):
                        entry["message"] = message_content
                        entry["product_ids"] = []

                history.append(entry)

            return history
        except Exception as e:
            logger.error(f"Error retrieving chat history (MongoDB): {e}")
            return []

    async def clear_history(self, identity_key: str):
        """Clear history."""
        try:
            await mongodb_client.db[self.collection_name].delete_many({"identity_key": identity_key})
            logger.info(f"Cleared chat history for {identity_key} (MongoDB)")
        except Exception as e:
            logger.error(f"Error clearing chat history (MongoDB): {e}")

    async def get_user_count(self) -> int:
        try:
            return len(await mongodb_client.db[self.collection_name].distinct("identity_key"))
        except Exception:
            return 0

    async def get_message_count_today(self, identity_key: str) -> int:
        """Count human messages sent today for rate limiting."""
        try:
            today_start = datetime.now(timezone.utc).replace(
                hour=0, minute=0, second=0, microsecond=0
            )
            count = await mongodb_client.db[self.collection_name].count_documents({
                "identity_key": identity_key,
                "is_human": True,
                "timestamp": {"$gte": today_start},
            })
            return count
        except Exception as e:
            logger.error(f"Error counting messages for {identity_key} (MongoDB): {e}")
            return 0

    async def close(self):
        pass


# --- Singleton ---
_instance: Any = None


async def get_conversation_manager():
    """Return MongoDB manager."""
    global _instance
    if _instance is None:
        _instance = MongoDBConversationManager()
        await _instance.initialize_table()
    return _instance
