import json
from flask import redirect, request, url_for
from werkzeug.exceptions import BadRequest, NotFound
from pysite.base_route import RouteView
from pysite.constants import TABLE_MANAGER_ROLES
from pysite.decorators import csrf, require_roles
from pysite.mixins import DBMixin
from pysite.tables import TABLES
class TableEditView(RouteView, DBMixin):
    path = "/tables/
/edit"
    name = "tables.edit"
    @require_roles(*TABLE_MANAGER_ROLES)
    def get(self, table):
        obj = TABLES.get(table)
        if not obj:
            # Unknown table
            raise NotFound()
        if obj.locked:
            return redirect(url_for("staff.tables.table", table=table, page=1), code=303)
        key = request.args.get("key")
        old_primary = None
        if key:
            db_obj = self.db.get(table, key)
            old_primary = key  # Provide the current document's primary key, in case it's modified
            document = json.dumps(  # Editor uses JSON
                db_obj,
                indent=4
            )
        else:
            document = json.dumps(  # Generate default document from key schema
                {k: "" for k in obj.keys},
                indent=4
            )
        return self.render(
            "staff/tables/edit.html", table=table, primary_key=obj.primary_key,
            document=document, old_primary=old_primary
        )
    @require_roles(*TABLE_MANAGER_ROLES)
    @csrf
    def post(self, table):
        obj = TABLES.get(TABLES)
        if not obj:
            # Unknown table
            raise NotFound()
        if obj.locked:
            raise BadRequest()
        data = request.form.get("json")
        old_primary = request.form.get("old_primary")
        if not data:
            # No data given (for some reason)
            document = json.dumps(
                {k: "" for k in obj.keys},
                indent=4
            )
            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=document,
                message="Please provide some data to save", old_primary=old_primary
            )
        try:
            data = json.loads(data)
        except json.JSONDecodeError as e:
            # Invalid JSON
            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
                message=f"Invalid JSON, please try again: {e}", old_primary=old_primary
            )
        if not data[obj.primary_key]:
            # No primary key value provided
            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
                message=f"Please provide a value for the primary key: {obj.primary_key}", old_primary=old_primary
            )
        if old_primary is None:
            self.db.insert(  # This is a new object, so just insert it
                table, data
            )
        elif old_primary == data[obj.primary_key]:
            self.db.insert(  # This is an update without a primary key change, replace the whole document
                table, data, conflict="replace"
            )
        else:
            self.db.delete(  # This is a primary key change, so we need to remove the old object
                table, old_primary
            )
            self.db.insert(
                table, data,
            )
        return redirect(url_for("staff.tables.table", table=table, page=1), code=303)