from datetime import datetime, timedelta
from typing import Any, Optional, Tuple

import jwt
from passlib.context import CryptContext

from src.core.config import settings

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> Tuple[str, datetime]:
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.JWT_EXPIRES)

    to_encode.update({"expires_at": expire.timestamp()})

    if "user" in to_encode and isinstance(to_encode["user"], dict):
        for key, value in to_encode["user"].items():
            if isinstance(value, datetime):
                to_encode["user"][key] = value.isoformat()

    print(f"============to_encode==================={to_encode}")

    encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET, algorithm=settings.JWT_ALGORITHM)
    return (encoded_jwt, expire)


def verify_access_token(token: str) -> Any:
    try:
        decoded_token = jwt.decode(token, settings.JWT_SECRET, algorithms=[settings.JWT_ALGORITHM])
        return decoded_token if decoded_token.get("expires_at") >= datetime.utcnow().timestamp() else None
    except:
        return None


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def encrypt_password(password: str):
    return pwd_context.hash(password)
