from datetime import datetime, timedelta
from pymongo.collection import Collection
from app.db import database
from ...models.saas.supportmodel import SupportActivityCreate, SupportActivityUpdate
from ...libraries.object import str_to_objectid
from typing import Optional, List
import logging

logger = logging.getLogger(__name__)
# Use a single collection for all support activities.
COLLECTION_NAME = "support_activities"

async def create_activity_service(activity: SupportActivityCreate, db: database.MongoDB) -> dict:
    """
    Insert a new support activity into the support_activities collection.
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        activity_data = activity.dict()
        activity_data["created_date"] = datetime.utcnow()
        result = activities_collection.insert_one(activity_data)
        activity_data["_id"] = str(result.inserted_id)
        activity_data["activity_id"] = activity_data["_id"]
        logger.info("Created activity %s", activity_data["activity_id"])
        return activity_data
    except Exception as e:
        logger.error("Error creating activity: %s", e)
        raise

async def list_activities_service(account_id: str, type_filter: Optional[str], skip: int, limit: int, db: database.MongoDB) -> List[dict]:
    """
    Retrieve a paginated list of support activities for the specified account.
    Optionally filter by activity type.
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        query = {"account_id": account_id}
        if type_filter:
            query["type"] = type_filter
        cursor = activities_collection.find(query).skip(skip).limit(limit).sort("created_date", -1)
        activities = []
        async for doc in cursor:
            doc["_id"] = str(doc["_id"])
            doc["activity_id"] = doc["_id"]
            activities.append(doc)
        return activities
    except Exception as e:
        logger.error("Error listing activities: %s", e)
        raise

async def get_activity_service(activity_id: str, db: database.MongoDB) -> Optional[dict]:
    """
    Retrieve a single support activity by its ID.
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        activity = activities_collection.find_one({"_id": str_to_objectid(activity_id)})
        if activity:
            activity["_id"] = str(activity["_id"])
            activity["activity_id"] = activity["_id"]
        return activity
    except Exception as e:
        logger.error("Error retrieving activity %s: %s", activity_id, e)
        raise

async def update_activity_service(activity_id: str, activity_update: SupportActivityUpdate, db: database.MongoDB) -> Optional[dict]:
    """
    Update an existing support activity.
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        update_data = activity_update.dict(exclude_unset=True)
        result = activities_collection.update_one({"_id": str_to_objectid(activity_id)}, {"$set": update_data})
        if result.matched_count == 0:
            return None
        activity = activities_collection.find_one({"_id": str_to_objectid(activity_id)})
        if activity:
            activity["_id"] = str(activity["_id"])
            activity["activity_id"] = activity["_id"]
        return activity
    except Exception as e:
        logger.error("Error updating activity %s: %s", activity_id, e)
        raise

async def delete_activity_service(activity_id: str, db: database.MongoDB) -> Optional[dict]:
    """
    Delete a support activity and return the deleted record.
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        activity = activities_collection.find_one({"_id": str_to_objectid(activity_id)})
        if not activity:
            return None
        activities_collection.delete_one({"_id": str_to_objectid(activity_id)})
        activity["_id"] = str(activity["_id"])
        activity["activity_id"] = activity["_id"]
        return activity
    except Exception as e:
        logger.error("Error deleting activity %s: %s", activity_id, e)
        raise

async def get_support_dashboard_service(account_id: str, db: database.MongoDB) -> dict:
    """
    Aggregate support metrics for an account:
      - Total count of support activities (of type 'comment' or 'note')
      - Count of upcoming meetings (activity type 'meeting' with scheduled date in additional_data)
      - For pipeline, the latest update might be shown elsewhere (here set as None)
    """
    try:
        activities_collection: Collection = db[COLLECTION_NAME]
        comments_count = activities_collection.count_documents({
            "account_id": account_id,
            "type": {"$in": ["comment", "note"]}
        })
        now = datetime.utcnow()
        meetings_cursor = activities_collection.find({
            "account_id": account_id,
            "type": "meeting",
            "additional_data.scheduled_date": {"$gte": now}
        })
        meetings_count = 0
        async for _ in meetings_cursor:
            meetings_count += 1

        dashboard = {
            "comments_count": comments_count,
            "upcoming_meetings_count": meetings_count,
            "trial_days_remaining": None,  # Trial details come from subscriptions module
            "last_updated": now.isoformat()
        }
        return dashboard
    except Exception as e:
        logger.error("Error aggregating dashboard metrics: %s", e)
        raise

async def update_pipeline_status_service(account_id: str, new_status: str, db: database.MongoDB) -> dict:
    """
    Update the sales pipeline status for an account.
    This function does two things:
      1. Updates the account record in the 'accounts' collection.
      2. Inserts a support activity record of type 'pipeline_update' to log the change.
    """
    try:
        accounts_collection = db["accounts"]
        account = accounts_collection.find_one({"_id": str_to_objectid(account_id)})
        if not account:
            raise ValueError("Account not found")
        old_status = account.get("sales_pipeline_status", "unknown")
        accounts_collection.update_one(
            {"_id": str_to_objectid(account_id)},
            {"$set": {"sales_pipeline_status": new_status, "updated_date": datetime.utcnow()}}
        )
        
        # Prepare the support activity record
        activity_data = {
            "type": "pipeline_update",
            "account_id": account_id,
            "user_id": None,  # Optionally, pass current user's ID if available
            "content": f"Pipeline status changed from {old_status} to {new_status}",
            "additional_data": {"old_status": old_status, "new_status": new_status},
            "created_date": datetime.utcnow()
        }
        activities_collection: Collection = db[COLLECTION_NAME]
        result = activities_collection.insert_one(activity_data)
        activity_data["_id"] = str(result.inserted_id)
        activity_data["activity_id"] = activity_data["_id"]
        return activity_data
    except Exception as e:
        logger.error("Error updating pipeline status for account %s: %s", account_id, e)
        raise
