"""/api/auth/login, /api/auth/logout, /api/auth/me."""

from __future__ import annotations

import os

from fastapi import APIRouter, Depends, HTTPException, Request, Response, status

from cyclone.auth import rate_limit, sessions, users
from cyclone.auth.deps import get_current_user
from cyclone.db import SessionLocal

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

COOKIE_NAME = "cyclone_session"
COOKIE_MAX_AGE = 86400  # 24h


def _is_https(request: Request) -> bool:
    if request.url.scheme == "https":
        return True
    return os.environ.get("CYCLONE_BEHIND_HTTPS") == "1"


def _set_cookie(response: Response, sid: str, request: Request) -> None:
    response.set_cookie(
        key=COOKIE_NAME,
        value=sid,
        max_age=COOKIE_MAX_AGE,
        path="/api",
        httponly=True,
        samesite="lax",
        secure=_is_https(request),
    )


def _clear_cookie(response: Response) -> None:
    response.delete_cookie(key=COOKIE_NAME, path="/api")


@router.post("/login")
def login(body: dict, request: Request, response: Response):
    username = (body.get("username") or "").strip()
    password = body.get("password") or ""
    if not username or not password:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="username and password are required",
        )

    retry_after = rate_limit.check(username)
    if retry_after > 0:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail="rate_limited",
            headers={"Retry-After": str(retry_after)},
        )

    with SessionLocal()() as db:
        user = users.get_by_username(db, username)
        if user is None or not users.verify_password(password, user.password_hash):
            rate_limit.record_failure(username)
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="invalid_credentials",
            )
        if user.disabled_at is not None:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="account_disabled",
            )

        sid, _ = sessions.create(db, user_id=user.id)
        rate_limit.reset(username)
        public = users.to_public(user)

    _set_cookie(response, sid, request)
    return public


@router.post("/logout")
def logout(
    request: Request,
    response: Response,
    _user: dict = Depends(get_current_user),
):
    sid = request.cookies.get(COOKIE_NAME)
    if sid:
        with SessionLocal()() as db:
            sessions.delete(db, sid)
    _clear_cookie(response)
    return Response(status_code=status.HTTP_204_NO_CONTENT)


@router.get("/me")
def me(user: dict = Depends(get_current_user)):
    return user
