#!/usr/bin/env python3

from datetime import timedelta
import logging
import re

from .util import is_logged_in, salt

from flask import (
    Blueprint,
    current_app,
    flash,
    redirect,
    render_template,
    request,
)
from tentacles.globals import ctx


log = logging.getLogger(__name__)
BLUEPRINT = Blueprint("user", __name__)


@BLUEPRINT.route("/")
def root():
    return (
        render_template(
            "index.html.j2",
        ),
        200,
    )


@BLUEPRINT.route("/user/login", methods=["GET"])
def get_login():
    if is_logged_in():
        return redirect("/")

    else:
        return render_template("login.html.j2")


@BLUEPRINT.route("/user/login", methods=["POST"])
def post_login():
    if row := ctx.db.try_login(
        username=(username := request.form["username"]),
        password=salt(request.form["password"]),
        ttl=timedelta(days=1),
    ):
        resp = redirect("/")
        resp.set_cookie("sid", row.id)
        flash(f"Welcome, {username}", category="success")
        return resp

    else:
        flash("Incorrect username/password", category="error")
        return render_template("login.html.j2")


@BLUEPRINT.route("/user/register", methods=["GET"])
def get_register():
    if is_logged_in():
        return redirect("/")

    else:
        return render_template("register.html.j2")


@BLUEPRINT.route("/user/register", methods=["POST"])
def post_register():
    try:
        username = request.form["username"]
        email = request.form["email"]
        has_config = False
        group_id = 1  # Normal users
        status_id = -3  # Unverified

        for user_config in current_app.config.get("users", []):
            if user_config["email"] == email:
                has_config = True

                if "group_id" in user_config:
                    group_id = user_config["group_id"]

                if "status_id" in user_config:
                    status_id = user_config["status_id"]

                break

        if user := ctx.db.try_create_user(
            username=username,
            email=email,
            password=salt(request.form["password"]),
            gid=group_id,
            sid=status_id,
        ):
            if user.status_id == -3:
                ctx.db.create_email(
                    uid=user.id,
                    subject="Tentacles email confirmation",
                    body=render_template(
                        "verification_email.html.j2",
                        username=user.name,
                        token_id=user.verification_token,
                        base_url=request.root_url,
                    ),
                )

                flash(
                    "Please check your email for a verification request",
                    category="success",
                )

            elif user.status_id == 1:
                # Do the entire approval dance just to be absolutely sure any statically configured users work
                ctx.db.try_verify_user(token=user.verification_token)
                ctx.db.approve_user(uid=user.id)
                ctx.db.enable_user(uid=user.id)

                flash("Welcome, please log in", category="success")

        return render_template("register.html.j2")

    except Exception as e:
        log.exception("Error encountered while registering a user...")

    flash("Unable to register that username", category="error")
    return render_template("register.html.j2")


@BLUEPRINT.route("/user/verify", methods=["GET", "POST"])
def verify():
    token = request.args.get("token", "")
    row = ctx.db.try_verify_user(token=token)
    if row:
        flash(
            f"Thanks for verifying your email {row.name}! You'll receive another email when your account is ready for use.",
            category="success",
        )
    return redirect("/user/login")


@BLUEPRINT.route("/user/logout")
def logout():
    # Invalidate the user's authorization
    ctx.db.delete_key(uid=ctx.uid, kid=ctx.sid)
    resp = redirect("/")
    resp.set_cookie("sid", "")
    return resp


@BLUEPRINT.route("/user", methods=["GET"])
def get_settings():
    if not is_logged_in():
        return redirect("/")

    return render_template("user.html.j2")


@BLUEPRINT.route("/user", methods=["POST"])
def post_settings():
    if request.form["action"] == "add":
        ttl_spec = request.form.get("ttl", "")
        if ttl_spec == "forever":
            ttl = None
        elif m := re.fullmatch(r"(\d+)d", ttl_spec):
            ttl = timedelta(days=int(m.group(1)))
        else:
            flash("Bad request", category="error")
            return render_template("user.html.j2"), 400

        ctx.db.create_key(
            uid=ctx.uid, ttl=ttl, name=request.form.get("name", "anonymous")
        )
        flash("Key created", category="success")

    elif request.form["action"] == "revoke":
        ctx.db.delete_key(ctx.uid, request.form.get("id"))
        flash("Key revoked", category="success")

    else:
        flash("Bad request", category="error")
        return render_template("user.html.j2"), 400

    return render_template("user.html.j2")
