from typing import Annotated

from fastapi import APIRouter, Cookie, Depends, HTTPException, Response, status
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession

from app.auth.deps import CurrentUser, current_user
from app.auth.security import (
    create_session,
    delete_session,
    hash_password,
    verify_password,
)
from app.config import settings
from app.db import get_session
from app.schemas.auth import LoginRequest, Me, PasswordChangeRequest

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


@router.post("/login")
async def login(
    payload: LoginRequest,
    response: Response,
    session: Annotated[AsyncSession, Depends(get_session)],
) -> Me:
    row = (
        await session.execute(
            text(
                "SELECT id::text, email, hashed_password, role, is_active FROM users WHERE email = :e"
            ),
            {"e": payload.email},
        )
    ).first()
    if not row or not row[4] or not verify_password(payload.password, row[2]):
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "invalid credentials")

    token, expires = await create_session(session, row[0])
    await session.commit()

    response.set_cookie(
        key=settings.SESSION_COOKIE_NAME,
        value=token,
        max_age=settings.SESSION_LIFETIME_SECONDS,
        httponly=True,
        samesite="lax",
        secure=False,
        path="/",
    )
    return Me(id=row[0], email=row[1], role=row[3])


@router.post("/logout")
async def logout(
    response: Response,
    session: Annotated[AsyncSession, Depends(get_session)],
    session_token: Annotated[str | None, Cookie(alias=settings.SESSION_COOKIE_NAME)] = None,
) -> dict[str, bool]:
    if session_token:
        await delete_session(session, session_token)
        await session.commit()
    response.delete_cookie(settings.SESSION_COOKIE_NAME, path="/")
    return {"ok": True}


@router.get("/me")
async def me(user: Annotated[CurrentUser, Depends(current_user)]) -> Me:
    return Me(id=user.id, email=user.email, role=user.role)


@router.post("/password")
async def change_password(
    payload: PasswordChangeRequest,
    user: Annotated[CurrentUser, Depends(current_user)],
    session: Annotated[AsyncSession, Depends(get_session)],
) -> dict[str, bool]:
    row = (
        await session.execute(
            text("SELECT hashed_password FROM users WHERE id = :id"), {"id": user.id}
        )
    ).first()
    if not row or not verify_password(payload.current_password, row[0]):
        raise HTTPException(status.HTTP_400_BAD_REQUEST, "current password mismatch")
    await session.execute(
        text("UPDATE users SET hashed_password = :h WHERE id = :id"),
        {"h": hash_password(payload.new_password), "id": user.id},
    )
    await session.commit()
    return {"ok": True}
