import os
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, HTTPException, Body
from sqlalchemy.orm import Session
from fastapi_login import LoginManager
from fastapi_login.exceptions import InvalidCredentialsException
from fastapi.security import OAuth2PasswordRequestForm

from db.db_connection import get_db
from db.models.user_model import User, UserCreate, UserResponse
from db.models.utils import hash_password, verify_password

# ===============================
# Load environment variables
# ===============================
load_dotenv(dotenv_path=".env.local")
SECRET = os.getenv("SECRET_KEY")

if not SECRET:
    raise ValueError("SECRET_KEY is not set in the .env.local file")

manager = LoginManager(SECRET, token_url="/auth/login")

# ===============================
# User Loader Callback (Required)
@manager.user_loader
def load_user(email: str):
    db = next(get_db())  
    return db.query(User).filter(User.email == email).first()

# ===============================
# Router
# ===============================
router = APIRouter(
    prefix="/auth",
    tags=["Authentication"]
)

# ===============================
# Example payloads
# ===============================
register_example = {
    "email": "johndoe@example.com",
    "password": "strongpassword123",
    "full_name": "John Doe",
    "phone": "+60123456789"
}

# ===============================
# Custom Dependency for Protected Routes
# ===============================
def get_current_user_with_db(
    user_email: str = Depends(manager),   # manager now uses the user_loader
    db: Session = Depends(get_db)
):
    user = db.query(User).filter(User.email == user_email).first()
    if not user:
        raise HTTPException(
            status_code=401,
            detail="Could not validate credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return user

# ===============================
# Routes
# ===============================
@router.post("/register", response_model=UserResponse)
def register(user_data: UserCreate = Body(..., example=register_example),
             db: Session = Depends(get_db)):
    """
    Register a new user using email and password.
    """
    existing_user = db.query(User).filter(User.email == user_data.email).first()
    if existing_user:
        raise HTTPException(status_code=400, detail="Email already registered")

    new_user = User(
        email=user_data.email,
        hashed_password=hash_password(user_data.password),
        full_name=user_data.full_name,
        phone=user_data.phone
    )
    db.add(new_user)
    db.commit()
    db.refresh(new_user)
    return new_user


@router.post("/login")
def login(form_data: OAuth2PasswordRequestForm = Depends(),
          db: Session = Depends(get_db)):
    """
    Login with OAuth2 form (Swagger Authorize popup works).
    - username = email
    - password = user password
    """
    user = db.query(User).filter(User.email == form_data.username).first()

    if not user or not verify_password(form_data.password, user.hashed_password):
        raise InvalidCredentialsException

    access_token = manager.create_access_token(data={"sub": user.email})

    return {
        "access_token": access_token,
        "token_type": "bearer",
        "user": {
            "id": user.id,
            "email": user.email,
            "full_name": user.full_name,
            "phone": user.phone,
            "is_active": user.is_active
        }
    }


@router.get("/me", response_model=UserResponse)
def get_current_user(user: User = Depends(get_current_user_with_db)):
    """
    Get the current logged-in user.
    """
    return user
