from starlette.requests import Request
from starlette.responses import RedirectResponse, JSONResponse

from api.auth.keycloak_client import Keycloak
from api.route import Route
from core.environment import Environment
from core.logger import Logger
from data.schemas.administration.user import User
from data.schemas.administration.user_dao import userDao
from data.schemas.public.user_invitation import UserInvitation
from data.schemas.public.user_invitation_dao import userInvitationDao
from data.schemas.public.user_space_user import UserSpaceUser
from data.schemas.public.user_space_user_dao import userSpaceUserDao

BasePath = f"/api/invitation"
logger = Logger(__name__)


def _redirect_to_client():
    client_urls = Environment.get("CLIENT_URLS", str)
    if client_urls is None:
        return JSONResponse({"message": "Invitation accepted."})

    return RedirectResponse(client_urls.split(",")[0], status_code=303)


@Route.get(f"{BasePath}/accept/{{invitation_id:path}}")
async def accept_invitation(request: Request):
    invitation_id = request.path_params["invitation_id"]

    user_invitation = await userInvitationDao.find_single_by(
        [{UserInvitation.invitation: invitation_id}]
    )
    if user_invitation is None:
        return JSONResponse({"error": "Invitation not found."}, 404)

    if user_invitation.deleted:
        return _redirect_to_client()

    keycloak_user = Keycloak.admin.get_users({"email": user_invitation.email})
    if len(keycloak_user) == 0:
        redirect_uri = f"{str(request.base_url)}api/invitation/accept/{invitation_id}"
        registration_url = f"{Keycloak.url}/realms/{Keycloak.realm}/protocol/openid-connect/auth?prompt=create&client_id={Keycloak.client_id}&response_type=code&scope=openid&redirect_uri={redirect_uri}"
        return RedirectResponse(registration_url, status_code=303)

    if user_invitation.email not in [
        x.email for x in await userDao.find_by([{User.deleted: False}])
    ]:
        user_id = await userDao.create(User(0, keycloak_user[0]["id"]))
        await userSpaceUserDao.create(
            UserSpaceUser(0, user_invitation.user_space_id, user_id)
        )

    await userInvitationDao.delete(user_invitation)

    return _redirect_to_client()


@Route.get(f"{BasePath}/user-space/accept/{{invitation_id:path}}")
async def accept_user_space_invitation(request: Request):
    invitation_id = request.path_params["invitation_id"]

    user_space_user = await userSpaceUserDao.find_single_by(
        [{UserSpaceUser.invitation: invitation_id}, {UserSpaceUser.deleted: False}]
    )
    if user_space_user is None:
        return _redirect_to_client()

    user_space_user.invitation = None
    await userSpaceUserDao.update(user_space_user)

    return _redirect_to_client()
