#!/usr/bin/env python3

"""The core app entrypoint."""

from datetime import datetime
from pathlib import Path
import tomllib

import click
from flask import Flask, request
from tentacles.blueprints import (
    api,
    file_ui,
    job_ui,
    printer_ui,
    user_ui,
)
from tentacles.globals import _ctx, Ctx, ctx
from tentacles.store import Store
from tentacles.workers import create_workers


@click.group()
def cli():
    pass


def store_factory(app):
    store = Store(app.config.get("db", {}).get("uri"))
    store.connect()
    return store


def custom_ctx(app, wsgi_app):
    def helper(environ, start_response):
        store = store_factory(app)
        token = _ctx.set(Ctx(store))
        try:
            return wsgi_app(environ, start_response)
        finally:
            _ctx.reset(token)
            store.close()

    return helper


def create_j2_request_global(app):
    app.jinja_env.globals["ctx"] = ctx
    app.jinja_env.globals["request"] = request
    app.jinja_env.globals["datetime"] = datetime


def user_session():
    if (session_id := request.cookies.get("sid", "")) and (
        uid := ctx.db.try_key(session_id)
    ):
        ctx.sid = session_id
        ctx.uid = uid
        _id, gid, name, _email, _hash, _status, _verification = ctx.db.fetch_user(uid)
        ctx.gid = gid
        ctx.username = name
        ctx.is_admin = gid == 0


@cli.command()
@click.option("--hostname", "hostname", type=str, default="0.0.0.0")
@click.option("--port", "port", type=int, default=8080)
@click.option("--config", type=Path)
def serve(hostname: str, port: int, config: Path):
    app = Flask(__name__)
    if config:
        with open(config, "rb") as fp:
            app.config.update(tomllib.load(fp))

    print(app.config)

    # Before first request
    create_j2_request_global(app)
    shutdown_event = create_workers(lambda: store_factory(app))

    # Before request
    app.before_request(user_session)

    # Blueprints
    app.register_blueprint(user_ui.BLUEPRINT)
    app.register_blueprint(printer_ui.BLUEPRINT)
    app.register_blueprint(job_ui.BLUEPRINT)
    app.register_blueprint(file_ui.BLUEPRINT)
    app.register_blueprint(api.BLUEPRINT)

    # Shove our middleware in there
    app.wsgi_app = custom_ctx(app, app.wsgi_app)

    # And run the blame thing
    try:
        app.run(host=hostname, port=port)
    finally:
        shutdown_event.set()


if __name__ == "__main__":
    cli()
