from datetime import datetime
from dateutil import parser
from typing import Optional, List, Dict, Any
from pymongo.errors import DuplicateKeyError
from fastapi import HTTPException
from bson import ObjectId

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.accountmodel import AccountCreate, AccountUpdate
from app.v1.services.sequence import get_next_sequence_value

COLLECTION_NAME = "accounts"
USER_COLLECTION_NAME = "users"

def create_account_service(account: AccountCreate, db: database.MongoDB) -> dict:
    account_data = account.dict()
    account_data["created_date"] = datetime.utcnow()

    # Enum conversion if present
    if "subscription_status" in account_data and account_data["subscription_status"]:
        account_data["subscription_status"] = account_data["subscription_status"].value
    if "subscription_type" in account_data and account_data["subscription_type"]:
        account_data["subscription_type"] = account_data["subscription_type"].value
    if "account_type" in account_data and account_data["account_type"]:
        account_data["account_type"] = account_data["account_type"].value

    # Incremental ID
    account_data["accounts_id"] = get_next_sequence_value("accounts_id", db)

    accounts_collection = db[COLLECTION_NAME]

    try:
        result = accounts_collection.insert_one(account_data)
    except DuplicateKeyError as e:
        if "email" in str(e):
            raise ValueError("Account with this email already exists.")
        elif "phone" in str(e):
            raise ValueError("Account with this phone number already exists.")
        else:
            raise ValueError("Duplicate key error.")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")

    # Mongo ObjectId as string
    account_id = str(result.inserted_id)
    account_data["_id"] = account_id
    #account_data["account_id"] = account_id

    # Update the user's document with Mongo _id
    users_collection = db[USER_COLLECTION_NAME]
    try:
        update_result = users_collection.update_one(
            {"_id": str_to_objectid(account.user_id)},
            {"$set": {"account_id": account_id}}
        )
    except Exception as e:
        print("Error updating user with account_id:", str(e))
        raise HTTPException(status_code=500, detail=f"Failed to update user: {str(e)}")

    if update_result.modified_count == 0:
        raise HTTPException(status_code=500, detail="Failed to update user with account_id.")

    # Welcome email
    subject = "Your Organization has been created!"
    body = f"Hello {account.full_name},\n\nThank you for signing up for our platform. We're excited to have you on board!"
    send_email(subject, body, account.email)

    return account_data

def get_account_service(account_id: str, db: database.MongoDB) -> dict:
    collection = db[COLLECTION_NAME]
    account = collection.find_one({"_id": str_to_objectid(account_id)})
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")
    account["_id"] = str(account["_id"])
    account["account_id"] = account["_id"]
    return account

def update_account_service(account_id: str, account_update: AccountUpdate, current_user: dict, db: database.MongoDB) -> dict:
    collection = db[COLLECTION_NAME]
    users_collection = db[USER_COLLECTION_NAME]

    existing_account = collection.find_one({"_id": str_to_objectid(account_id)})
    if not existing_account:
        raise HTTPException(status_code=404, detail="Account not found")

    user = users_collection.find_one({"_id": str_to_objectid(current_user.get("_id"))})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    if current_user.get("roles") != 1 and str(user.get("account_id")) != account_id:
        raise HTTPException(status_code=403, detail="Not authorized to update this account")

    updates = account_update.dict(exclude_unset=True)
    for key in ["subscription_status", "subscription_type", "account_type"]:
        if key in updates and hasattr(updates[key], "value"):
            updates[key] = updates[key].value

    collection.update_one({"_id": str_to_objectid(account_id)}, {"$set": updates})
    updated_account = collection.find_one({"_id": str_to_objectid(account_id)})
    if updated_account:
        updated_account["_id"] = str(updated_account["_id"])
        updated_account["account_id"] = updated_account["_id"]
        return updated_account
    raise HTTPException(status_code=404, detail="Account not found after update")

def delete_account_service(account_id: str, db: database.MongoDB) -> dict:
    collection = db[COLLECTION_NAME]
    account = collection.find_one({"_id": str_to_objectid(account_id)})
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")

    collection.delete_one({"_id": str_to_objectid(account_id)})
    account["_id"] = str(account["_id"])
    account["account_id"] = account["_id"]
    return account
