from datetime import datetime, timedelta

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import jwt
from pydantic import BaseModel
from sqlalchemy.orm import Session

from ..config import Config
from ..db import Connection, schemas

router = APIRouter(prefix="/user")
SCHEME = OAuth2PasswordBearer(
    tokenUrl=f".{router.prefix}/token",
)


class Token(BaseModel):
    access_token: str
    token_type: str


def create_access_token(
    data: dict,
    expires_delta: timedelta | None = None,
    config: Config = Depends(Config.get),
):
    to_encode = data.copy()
    if expires_delta is None:
        expires_delta = timedelta(minutes=15)

    to_encode.update({"exp": datetime.utcnow() + expires_delta})
    return jwt.encode(
        to_encode,
        config.jwt.secret,
        algorithm=config.jwt.hash_algorithm,
    )


@router.post("/auth", response_model=Token)
async def login(
    form_data: OAuth2PasswordRequestForm = Depends(),
    config: Config = Depends(Config.get),
    db: Session = Depends(Connection.get),
):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    user = schemas.User.get(db, form_data.username)
    if user is None:
        config.crypt_context.dummy_verify()
        raise credentials_exception

    if not user.verify(form_data.password):
        raise credentials_exception

    access_token = create_access_token(
        data={"sub": user.name},
        expires_delta=timedelta(minutes=config.jwt.expiry_minutes),
    )
    return {"access_token": access_token, "token_type": "bearer"}