
from datetime import datetime, timedelta, timezone
from typing import Optional
import re
from database import get_db
from models.models import User, AdminUser
from core.excption import NotFoundException 
from sqlalchemy.orm import Session
from fastapi import Depends, HTTPException
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
import jwt
from core.config import settings

security = HTTPBearer()


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encoded_jwt

def create_refresh_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(days=30)
    to_encode.update({"exp": expire, "type": "refresh"})
    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encoded_jwt

def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    try:
        payload = jwt.decode(credentials.credentials, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        identifier = payload.get("sub")
        if not identifier:
            raise HTTPException(status_code=401, detail="Invalid token")

        # Détecte si c'est un email ou un numéro de téléphone
        if re.match(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", identifier):
            return {"type": "email", "value": identifier}
        elif re.match(r"^\+?[0-9\s-]{8,}$", identifier):
            return {"type": "phone", "value": identifier}
        else:
            raise HTTPException(status_code=401, detail="Invalid identifier format in token")

    except jwt.PyJWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

def get_current_user(identifier: dict = Depends(verify_token), db: Session = Depends(get_db)):
    if identifier["type"] == "email":
        user = db.query(User).filter(User.email == identifier["value"]).first()
    else:  # phone
        user = db.query(User).filter(User.phone == identifier["value"]).first()

    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return user

def get_current_admin(identifier: dict = Depends(verify_token), db: Session = Depends(get_db)):
    if identifier["type"] == "email":
        user = db.query(AdminUser).filter(AdminUser.email == identifier["value"]).first()
    else:  # phone
        user = db.query(AdminUser).filter(AdminUser.phone == identifier["value"]).first()

    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return user
