from __future__ import annotations

from datetime import UTC, datetime

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

from app.api.dependencies import current_user
from app.db.session import get_session
from app.models.user import User
from app.core.security import hash_password, verify_password
from app.schemas.auth import ChangePasswordRequest, LoginRequest, TokenResponse, UserRead
from app.services.auth_service import AuthService
from app.core.config import settings

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


@router.post("/login", response_model=TokenResponse)
def login(payload: LoginRequest, session: Session = Depends(get_session)) -> TokenResponse:
    token, user = AuthService(session).login(payload.email, payload.password)
    return TokenResponse(
        access_token=token,
        expires_in=settings.access_token_minutes * 60,
        user=user,
    )


@router.get("/me", response_model=UserRead)
def me(user: User = Depends(current_user)) -> User:
    return user


@router.post("/change-password")
def change_password(
    payload: ChangePasswordRequest,
    user: User = Depends(current_user),
    session: Session = Depends(get_session),
) -> dict[str, str]:
    if not verify_password(payload.current_password, user.password_hash):
        raise HTTPException(status_code=422, detail="Das aktuelle Passwort ist falsch.")
    if payload.new_password != payload.new_password_confirmation:
        raise HTTPException(status_code=422, detail="Die neuen Passwoerter stimmen nicht ueberein.")
    if len(payload.new_password) < 12:
        raise HTTPException(status_code=422, detail="Das neue Passwort muss mindestens 12 Zeichen haben.")
    if verify_password(payload.new_password, user.password_hash):
        raise HTTPException(status_code=422, detail="Das neue Passwort darf nicht identisch zum alten sein.")

    user.password_hash = hash_password(payload.new_password)
    user.must_change_password = False
    user.password_changed_at = datetime.now(UTC)
    session.commit()
    return {"status": "ok"}
