#!/usr/bin/env python3

"""API endpoints supporting the 'ui'."""

from hashlib import sha3_256
import os
from typing import Optional

from flask import Blueprint, current_app, request
from tentacles.blueprints.util import (
    requires_admin,
    requires_auth,
)
from tentacles.globals import ctx


BLUEPRINT = Blueprint("api", __name__, url_prefix="/api")


####################################################################################################
# Printers
#
# The trick here is handling multipart uploads.
@requires_admin
@BLUEPRINT.route("/printers", methods=["POST"])
def create_printer():
    pass


@requires_auth
@BLUEPRINT.route("/printers", methods=["GET"])
@BLUEPRINT.route("/printers/", methods=["GET"])
def list_printers():
    return {
        "printers": [
            {"id": p.id, "name": p.name, "url": p.url} for p in ctx.db.list_printers()
        ]
    }, 200


@requires_admin
@BLUEPRINT.route("/printers", methods=["DELETE"])
def delete_printer():
    pass


####################################################################################################
# Files
#
# The trick here is handling multipart uploads.
@requires_auth
@BLUEPRINT.route("/files", methods=["POST"])
@BLUEPRINT.route("/files/<location>", methods=["POST"])
def create_file(location: Optional[str] = None):
    # This is the important one, because it's the one that PrusaSlicer et all use to upload jobs.

    if "file" not in request.files:
        return {"status": "error", "error": "No file to upload"}, 400

    file = request.files["file"]
    # If the user does not select a file, the browser submits an
    # empty file without a filename.
    if not file.filename:
        return {"status": "error", "error": "No filename provided"}, 400

    elif not file.filename.endswith(".gcode"):
        return {"status": "error", "error": "Non-gcode file specified"}, 400

    else:
        digest = sha3_256()
        digest.update(file.filename.encode())
        sanitized_filename = digest.hexdigest() + ".gcode"
        sanitized_path = os.path.join(
            current_app.config["UPLOAD_FOLDER"], sanitized_filename
        )
        file.save(sanitized_path)
        ctx.db.create_file(ctx.uid, file.filename, sanitized_path)

        return {"status": "ok"}, 202


@requires_auth
@BLUEPRINT.route("/files", methods=["GET"])
@BLUEPRINT.route("/files/", methods=["GET"])
def get_files():
    return {
        "files": [
            {
                "id": f.id,
                "filename": f.filename,
                "path": f.path,
                "owner": ctx.uid,
                "upload_date": f.upload_date,
            }
            for f in ctx.db.list_files(ctx.uid)
        ]
    }, 200


@requires_auth
@BLUEPRINT.route("/files", methods=["DELETE"])
def delete_file():
    pass


####################################################################################################
# Jobs
@requires_auth
@BLUEPRINT.route("/jobs", methods=["POST"])
def create_job():
    pass


@requires_auth
@BLUEPRINT.route("/jobs", methods=["GET"])
def get_jobs():
    return {
        "jobs": [
            {
                "id": j.id,
                "file_id": j.file_id,
                "started_at": j.started_at,
                "finished_at": j.finished_at,
                "printer_id": j.printer_id,
            }
            for j in ctx.db.list_jobs()
        ]
    }, 200


@requires_auth
@BLUEPRINT.route("/jobs", methods=["DELETE"])
def delete_job():
    pass


####################################################################################################
# API tokens
@requires_auth
@BLUEPRINT.route("/tokens", methods=["GET"])
def get_tokens():
    pass
