"""Auth endpoints."""
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, Response, Request
import jwt

from auth import (
    JWT_ALGORITHM, get_jwt_secret, hash_password, verify_password,
    create_access_token, create_refresh_token, set_auth_cookies, clear_auth_cookies,
)
from deps import get_db, get_current_user
from models import LoginIn, UserOut

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


def _serialize_user(user_doc: dict) -> dict:
    return {
        "id": str(user_doc["_id"]),
        "email": user_doc["email"],
        "name": user_doc.get("name", ""),
        "role": user_doc.get("role", "collaborator"),
        "department_id": user_doc.get("department_id"),
        "avatar_url": user_doc.get("avatar_url"),
        "active": user_doc.get("active", True),
        "must_change_password": user_doc.get("must_change_password", False),
        "created_at": user_doc.get("created_at"),
    }


@router.post("/login", response_model=UserOut)
async def login(payload: LoginIn, response: Response):
    db = get_db()
    email = payload.email.lower().strip()
    user = await db.users.find_one({"email": email})
    if not user or not verify_password(payload.password, user["password_hash"]):
        raise HTTPException(status_code=401, detail="Credenciales inválidas")
    if not user.get("active", True):
        raise HTTPException(status_code=403, detail="Cuenta no activada. Revisa tu email para el enlace de activación.")
    uid = str(user["_id"])
    access = create_access_token(uid, email, user["role"])
    refresh = create_refresh_token(uid)
    set_auth_cookies(response, access, refresh)
    return _serialize_user(user)


@router.post("/logout")
async def logout(response: Response):
    clear_auth_cookies(response)
    return {"ok": True}


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


@router.post("/refresh")
async def refresh(request: Request, response: Response):
    token = request.cookies.get("refresh_token")
    if not token:
        raise HTTPException(status_code=401, detail="Sin token de refresco")
    try:
        payload = jwt.decode(token, get_jwt_secret(), algorithms=[JWT_ALGORITHM])
        if payload.get("type") != "refresh":
            raise HTTPException(status_code=401, detail="Token inválido")
        from bson import ObjectId
        db = get_db()
        user = await db.users.find_one({"_id": ObjectId(payload["sub"])})
        if not user:
            raise HTTPException(status_code=401, detail="Usuario no encontrado")
        new_access = create_access_token(str(user["_id"]), user["email"], user["role"])
        new_refresh = create_refresh_token(str(user["_id"]))
        set_auth_cookies(response, new_access, new_refresh)
        return {"ok": True}
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token expirado")
    except jwt.InvalidTokenError:
        raise HTTPException(status_code=401, detail="Token inválido")
