from datetime import datetime
from typing import Optional

from bson import ObjectId
from fastapi import HTTPException, status
from pydantic import EmailStr
from ..database import db
from ..utils.auth_utils import get_password_hash
from ..models.user import User
from ..schemas.user import UserCreate, UserResponse


class UserService:
    def __init__(self):
        self.collection = db.user

    async def create_user(self, user: UserCreate) -> Optional[User]:
        # Check if email exists
        if await self.collection.find_one({"email": user.email}):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Email already registered"
            )

        # Prepare user data
        user_data = {
            "email": user.email,
            "name": user.name,
            "password": get_password_hash(user.password),
            "created_at": datetime.utcnow(),
            "updated_at": None
        }

        # Insert into database
        result = await self.collection.insert_one(user_data)

        # Get created user
        created_user = await self.collection.find_one({"_id": result.inserted_id})

        # Convert ObjectId to string before creating Pydantic model
        if created_user and "_id" in created_user:
            created_user["_id"] = str(created_user["_id"])

        # Create and return User model
        try:
            return User.parse_obj(created_user)
        except Exception as e:
            print(f"Error creating User model: {e}")
            print(f"Created user data: {created_user}")
            # Return raw data if model creation fails
            return created_user

    async def get_user_by_email(self, email: EmailStr) -> Optional[UserResponse]:
        user_dict = await self.collection.find_one({"email": email})
        if user_dict:
            user_dict["_id"] = str(user_dict["_id"])
        return UserResponse.from_user_in_db(user_dict)

    async def get_user_by_email_db(self, email: EmailStr) -> Optional[User]:
        user_dict = await self.collection.find_one({"email": email})
        if user_dict:
            user_dict["_id"] = str(user_dict["_id"])
        return user_dict

    async def get_user_by_id(self, user_id: str) -> Optional[UserResponse]:
        if not ObjectId.is_valid(user_id):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Invalid user ID"
            )
        user_dict = await self.collection.find_one({"_id": ObjectId(user_id)})
        if user_dict:
            user_dict["_id"] = str(user_dict["_id"])
        return UserResponse.from_user_in_db(user_dict)


user_service = UserService()