from __future__ import annotations

import json
from flask import g, jsonify, request
from sqlalchemy import text

from app import db
from app.api.system import bp
from app.core.system.permissions import READ_GOVERNANCE, require_permissions
from app.core.workbench.registry import DEFAULT_LAYOUT, WIDGET_REGISTRY, validate_layout
from app.models.result import failed, success


@bp.route("/workbench/registry", methods=["GET"])
@require_permissions(READ_GOVERNANCE)
def workbench_registry():
    return jsonify(success(WIDGET_REGISTRY))


@bp.route("/workbench/layout", methods=["GET"])
@require_permissions(READ_GOVERNANCE)
def get_workbench_layout():
    row = db.session.execute(text("SELECT layout_version, widgets FROM public.workbench_layouts WHERE user_id = CAST(:id AS uuid)"), {"id": g.current_user["id"]}).one_or_none()
    data = {"version": row[0], "widgets": row[1]} if row else {"version": 0, "widgets": DEFAULT_LAYOUT}
    return jsonify(success(data))


@bp.route("/workbench/layout", methods=["PUT"])
@require_permissions(READ_GOVERNANCE)
def put_workbench_layout():
    body = request.get_json(silent=True) or {}
    try:
        widgets = validate_layout(body.get("widgets"))
        expected = int(request.headers.get("If-Match", body.get("version", 0)))
    except (ValueError, TypeError) as exc:
        return jsonify(failed(str(exc), code=400)), 400
    current = db.session.execute(text("SELECT layout_version FROM public.workbench_layouts WHERE user_id = CAST(:id AS uuid) FOR UPDATE"), {"id": g.current_user["id"]}).scalar_one_or_none()
    if (current or 0) != expected:
        db.session.rollback()
        return jsonify(failed("布局已被其他会话修改", code=409, data={"current_version": current or 0})), 409
    new_version = expected + 1
    db.session.execute(text("INSERT INTO public.workbench_layouts (user_id, layout_version, widgets) VALUES (CAST(:id AS uuid), :version, CAST(:widgets AS jsonb)) ON CONFLICT (user_id) DO UPDATE SET layout_version = EXCLUDED.layout_version, widgets = EXCLUDED.widgets, updated_at = CURRENT_TIMESTAMP"), {"id": g.current_user["id"], "version": new_version, "widgets": json.dumps(widgets)})
    db.session.commit()
    return jsonify(success({"version": new_version, "widgets": widgets}))
