import os
import jwt
import time
import requests
from flask import abort
from flask import Blueprint
from flask import request
from flask import jsonify
from flask import redirect
from flask import current_app
from flask import session
from urllib.parse import unquote
from base64 import b64encode
from datetime import datetime
from sqlmodel import select
from sqlmodel import Session as SQLSession
from app.models.user import User

bp = Blueprint("auth", __name__)


@bp.route("/login")
def login():
    CLIENT_ID = current_app.config["CLIENT_ID"]
    REDIRECT_URI = current_app.config["REDIRECT_URI"]
    USER_STATE = b64encode(os.urandom(64)).decode("utf-8")
    UAA_AUTHORIZE_URI = current_app.config["UAA_AUTHORIZE_URI"]

    session["USER_STATE"] = USER_STATE

    UAA_LOGIN = f"{UAA_AUTHORIZE_URI}?client_id={CLIENT_ID}&response_type=code&redirect_uri={REDIRECT_URI}&state={USER_STATE}"

    return redirect(UAA_LOGIN)


@bp.route("/logout")
def logout():
    CLIENT_ID = current_app.config["CLIENT_ID"]
    REDIRECT_URI = current_app.config["REDIRECT_URI"]
    UAA_LOGOUT_URI = current_app.config["UAA_LOGOUT_URI"]
    UAA_LGOUT = f"{UAA_LOGOUT_URI}?client_id={CLIENT_ID}&redirect={REDIRECT_URI}"

    session.clear()
    requests.post(UAA_LGOUT)

    return redirect("/")


@bp.route("/callback")
def callback():
    # @url_param {string} code
    # @url_param {string} status
    code = request.args.get("code")
    state = request.args.get("state")

    if not code or not state:
        abort(400)

    UAA_TOKEN_URI = current_app.config["UAA_TOKEN_URI"]

    data = {
        "code": code,
        "grant_type": "authorization_code",
        "response_type": "token",
        "client_id": current_app.config["CLIENT_ID"],
        "client_secret": current_app.config["CLIENT_SECRET"],
        "redirect_uri": current_app.config["REDIRECT_URI"],
    }

    response = requests.post(UAA_TOKEN_URI, data=data)

    if response.status_code != 200:
        abort(response.status_code)

    response = response.json()

    token = response["access_token"]
    header = jwt.get_unverified_header(token)

    session["claims"] = jwt.decode(
        token, header["alg"], options={"verify_signature": False}
    )
    session["expiry"] = time.time() + (response["expires_in"] * 1000)
    session["refresh_token"] = response["refresh_token"]
    session["authenticated"] = True

    with SQLSession(current_app.engine) as s:
        query = select(User).where(User.email == session["claims"]["email"])
        user = s.exec(query).first()

        if user:
            # Account exists
            user.last_logon = datetime.now()
            s.add(user)
            s.commit()

        else:
            # Account does not exist
            new_user = User(
                user_name=session["claims"]["user_name"],
                email=session["claims"]["email"],
                last_logon=datetime.now(),
            )
            s.add(new_user)
            s.commit()

        user = s.exec(query).first()
        session["user"] = user.dict()

    return redirect("/")

jwt.decode flask.request.args.get requests.post flask.abort os.urandom jwt.get_unverified_header flask.redirect datetime.datetime.now sqlmodel.select flask.session.clear sqlmodel.Session flask.Blueprint time.time
[((438, 465), 'flask.Blueprint', 'Blueprint', (['"""auth"""', '__name__'], {}), "('auth', __name__)\n", (447, 465), False, 'from flask import Blueprint\n'), ((906, 925), 'flask.redirect', 'redirect', (['UAA_LOGIN'], {}), '(UAA_LOGIN)\n', (914, 925), False, 'from flask import redirect\n'), ((1210, 1225), 'flask.session.clear', 'session.clear', ([], {}), '()\n', (1223, 1225), False, 'from flask import session\n'), ((1230, 1254), 'requests.post', 'requests.post', (['UAA_LGOUT'], {}), '(UAA_LGOUT)\n', (1243, 1254), False, 'import requests\n'), ((1267, 1280), 'flask.redirect', 'redirect', (['"""/"""'], {}), "('/')\n", (1275, 1280), False, 'from flask import redirect\n'), ((1397, 1421), 'flask.request.args.get', 'request.args.get', (['"""code"""'], {}), "('code')\n", (1413, 1421), False, 'from flask import request\n'), ((1434, 1459), 'flask.request.args.get', 'request.args.get', (['"""state"""'], {}), "('state')\n", (1450, 1459), False, 'from flask import request\n'), ((1879, 1918), 'requests.post', 'requests.post', (['UAA_TOKEN_URI'], {'data': 'data'}), '(UAA_TOKEN_URI, data=data)\n', (1892, 1918), False, 'import requests\n'), ((2075, 2107), 'jwt.get_unverified_header', 'jwt.get_unverified_header', (['token'], {}), '(token)\n', (2100, 2107), False, 'import jwt\n'), ((2133, 2202), 'jwt.decode', 'jwt.decode', (['token', "header['alg']"], {'options': "{'verify_signature': False}"}), "(token, header['alg'], options={'verify_signature': False})\n", (2143, 2202), False, 'import jwt\n'), ((3065, 3078), 'flask.redirect', 'redirect', (['"""/"""'], {}), "('/')\n", (3073, 3078), False, 'from flask import redirect\n'), ((1499, 1509), 'flask.abort', 'abort', (['(400)'], {}), '(400)\n', (1504, 1509), False, 'from flask import abort\n'), ((1964, 1991), 'flask.abort', 'abort', (['response.status_code'], {}), '(response.status_code)\n', (1969, 1991), False, 'from flask import abort\n'), ((2241, 2252), 'time.time', 'time.time', ([], {}), '()\n', (2250, 2252), False, 'import time\n'), ((2390, 2420), 'sqlmodel.Session', 'SQLSession', (['current_app.engine'], {}), '(current_app.engine)\n', (2400, 2420), True, 'from sqlmodel import Session as SQLSession\n'), ((2618, 2632), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2630, 2632), False, 'from datetime import datetime\n'), ((630, 644), 'os.urandom', 'os.urandom', (['(64)'], {}), '(64)\n', (640, 644), False, 'import os\n'), ((2443, 2455), 'sqlmodel.select', 'select', (['User'], {}), '(User)\n', (2449, 2455), False, 'from sqlmodel import select\n'), ((2896, 2910), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2908, 2910), False, 'from datetime import datetime\n')]