from datetime import datetime
from pymongo.errors import DuplicateKeyError
from app.db import database
from app.v1.integrations.SMTPmailer import send_email
from app.v1.libraries.object import str_to_objectid
from app.v1.models.saas.partners import PartnerCreate, PartnerUpdate, Partner, Partners
from app.v1.models.saas.usersmodel import User
from typing import Optional

COLLECTION_NAME = "users"
USER_COLLECTION_NAME = "users"

def create_partner_service(partner: PartnerCreate, db: database.MongoDB) -> dict:
    partner_data = partner.dict()
    partner_data["created_date"] = datetime.utcnow()
    
    partners_collection = db[COLLECTION_NAME]
    
    try:
        result = partners_collection.insert_one(partner_data)
    except DuplicateKeyError as e:
        if "email" in str(e):
            raise ValueError("Partner with this email already exists.")
        elif "mobile" in str(e):
            raise ValueError("Partner with this mobile number already exists.")
        else:
            raise ValueError("Duplicate key error.")
    
    # (Optional) Update the user with the new partner_id if needed.
    # For example, you could call an update function here:
    # update_user_partner_id(partner.user_id, str(result.inserted_id), db)
    
    # Send a welcome email
    subject = "Your Organization has been created!"
    body = f"Hello {partner.name},\n\nThank you for signing up for our platform. We're excited to have you on board!"
    send_email(subject, body, partner.email)
    
    # Prepare and return the created partner data
    partner_data["_id"] = str(result.inserted_id)
    partner_data["partner_id"] = partner_data["_id"]
    return partner_data

def get_partners_service(
    skip: int, 
    limit: int, 
    q: str, 
    partner_type: str, 
    created_date_from: Optional[str],
    created_date_to: Optional[str],
    status: Optional[str], 
    db: database.MongoDB, 
    current_user: User
) -> dict:
    collection = db[COLLECTION_NAME]
    
    # Example role check: only users with role 1 (e.g., admin , moderators, sales, partners) can list partners
    if current_user.get("roles", 0) != 1 and current_user.get("roles", 0) != 2 :
        raise ValueError("Not permitted to view partners.")
    
    query = {}
    if q:
        regex_query = {"$regex": q, "$options": "i"}
        query["$or"] = [
            {"name": regex_query},
            {"email": regex_query}
        ]
    
    if partner_type:
        query["partner_type"] = partner_type
    
    if status:
        if status.lower() == "active":
            query["is_active"] = True
        elif status.lower() == "inactive":
            query["is_active"] = False

    if created_date_from or created_date_to:
        date_filter = {}
        if created_date_from:
            date_filter["$gte"] = datetime.strptime(created_date_from, "%Y-%m-%d")
        if created_date_to:
            date_filter["$lte"] = datetime.strptime(created_date_to, "%Y-%m-%d")
        query["created_date"] = date_filter

    query["roles"] = 3
    
    partners_cursor = collection.find(query).skip(skip).limit(limit)
    partners_list = []
    for partner in partners_cursor:
        partner["id"] = str(partner["_id"])
        partner["partner_id"] = str(partner["_id"])
        partner.setdefault("partner_name", partner.get("name", ""))
        partner.setdefault("title", "Partner")  # or any default title
        if "created_date" in partner and isinstance(partner["created_date"], datetime):
            partner["created_date"] = partner["created_date"].isoformat()
        partners_list.append(partner)
    
    #print(" Partners List as follows ,,, " , partners_list)
    total_count = collection.count_documents(query)
    
    return {"total_count": total_count, "partners": partners_list}

def get_partner_service(partner_id: str, db: database.MongoDB) -> dict:
    collection = db[COLLECTION_NAME]
    partner = collection.find_one({"_id": str_to_objectid(partner_id)})
    if partner:
        partner["_id"] = str(partner["_id"])
        partner["partner_id"] = partner["_id"]
    return partner

def update_partner_service(
    partner_id: str, 
    partner_update: PartnerUpdate, 
    current_user: dict, 
    db: database.MongoDB
) -> dict:
    partners_collection = db[COLLECTION_NAME]
    users_collection = db[USER_COLLECTION_NAME]
    
    existing_partner = partners_collection.find_one({"_id": str_to_objectid(partner_id)})
    if not existing_partner:
        raise ValueError("Partner not found")
    
    user_document = users_collection.find_one({"_id": current_user["_id"]})
    if not user_document:
        raise ValueError("User not found")
    
    # Check if the current user is authorized to update the partner
    if str(user_document.get("partner_id")) != partner_id:
        raise ValueError("Not authorized to update this partner")
    
    partner_updates = partner_update.dict(exclude={"user_id"})
    partner_updates.pop("roles", None)  # Remove roles field if present
    
    # For example, only users with role 3 may update the partner
    if user_document.get("roles") == 3:  #Role 3== Partner Admin
        partners_collection.update_one({"_id": str_to_objectid(partner_id)}, {"$set": partner_updates})
    
    # Optionally update user data in the users collection
    user_update_data = {"name": partner_update.name, "mobile": partner_update.mobile}
    users_collection.update_one({"_id": current_user["_id"]}, {"$set": user_update_data})
    
    updated_partner = partners_collection.find_one({"_id": str_to_objectid(partner_id)})
    if updated_partner:
        updated_partner["_id"] = str(updated_partner["_id"])
        updated_partner["partner_id"] = updated_partner["_id"]
        return updated_partner
    else:
        raise ValueError("Partner not found after update")

def delete_partner_service(partner_id: str, db: database.MongoDB) -> dict:
    collection = db[COLLECTION_NAME]
    partner = collection.find_one({"_id": str_to_objectid(partner_id)})
    if not partner:
        raise ValueError("Partner not found")
    collection.delete_one({"_id": str_to_objectid(partner_id)})
    partner["_id"] = str(partner["_id"])
    partner["partner_id"] = partner["_id"]
    return partner
