from fastapi import APIRouter, Request, Depends, HTTPException
from fastapi.responses import JSONResponse, RedirectResponse
from sqlalchemy.orm import Session

from app.models.database import get_db
from app.models.user import User
from app.models.role_permission import Role, Permission
from app.services.auth_service import hash_password, verify_password, create_access_token, decode_access_token
from app.schemas import LoginRequest

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


def get_current_user(request: Request, db: Session = Depends(get_db)):
    token = request.cookies.get("access_token")
    if not token:
        raise HTTPException(status_code=401, detail="Not authenticated")
    payload = decode_access_token(token)
    if not payload:
        raise HTTPException(status_code=401, detail="Invalid token")
    user = db.query(User).filter(User.id == payload.get("user_id"), User.active == True).first()
    if not user:
        # Check if user exists but is inactive
        inactive = db.query(User).filter(User.id == payload.get("user_id"), User.active == False).first()
        detail = "Cuenta desactivada" if inactive else "User not found"
        raise HTTPException(status_code=401, detail=detail)
    return user


@router.post("/login", summary="Iniciar sesión", description="Autentica al usuario por email y contraseña. Devuelve token JWT en cookie HttpOnly con duración de 8 horas.")
async def login(body: LoginRequest, request: Request, db: Session = Depends(get_db)):
    email = body.email
    password = body.password

    user = db.query(User).filter(User.email == email, User.active == True).first()
    if not user or not verify_password(password, user.password_hash):
        return JSONResponse({"error": "Credenciales invalidas"}, status_code=401)

    token = create_access_token({"user_id": user.id, "email": user.email, "role": user.role})
    response = JSONResponse({"ok": True, "user": {"name": user.name, "email": user.email, "role": user.role}})
    response.set_cookie(
        key="access_token",
        value=token,
        httponly=True,
        secure=True,
        samesite="lax",
        max_age=28800,
    )
    return response


@router.post("/logout", summary="Cerrar sesión", description="Elimina la cookie de sesión JWT del navegador.")
async def logout():
    response = JSONResponse({"ok": True})
    response.delete_cookie("access_token")
    return response


@router.get("/me", summary="Perfil del usuario autenticado", description="Devuelve los datos del usuario actual y la lista de permisos según su rol.")
async def me(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    return {
        "id": current_user.id,
        "name": current_user.name,
        "email": current_user.email,
        "role": current_user.role,
        "permissions": sorted(list(get_user_permissions(current_user, db))),
    }


def get_user_permissions(user, db: Session = None):
    """Retorna set de codigos de permiso del usuario segun su rol."""
    if not db:
        from app.models.database import get_tenant_session
        db = get_tenant_session()
        local_db = True
    else:
        local_db = False
    try:
        role = db.query(Role).filter(Role.name == user.role).first()
        if not role:
            return set()
        if role.all_permissions:
            perms = db.query(Permission).all()
        else:
            perms = role.permissions
        codes = {p.code for p in perms}
        return codes
    finally:
        if local_db:
            db.close()

def require_permission(perm_code: str):
    """Decorador/dependencia que verifica un permiso especifico."""
    async def checker(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
        perms = get_user_permissions(current_user, db)
        if perm_code not in perms:
            raise HTTPException(status_code=403, detail=f"Permiso denegado: {perm_code}")
        return current_user
    return checker
