from typing import Optional, Tuple

import flask

from abstra_internals.controllers.presence import PresenceController
from abstra_internals.environment import EDITOR_MODE, PROJECT_ID
from abstra_internals.repositories.factory import Repositories
from abstra_internals.services.jwt import decode_jwt


def _current_user() -> Optional[Tuple[str, str]]:
    if EDITOR_MODE == "local":
        return "local", "local"

    token = flask.request.cookies.get("editor_auth")
    if not token:
        return None
    claims = decode_jwt(token, aud=f"web-editor-{PROJECT_ID}")
    if not claims:
        return None
    email = claims.get("email")
    if not email:
        return None
    name = claims.get("name") or email
    return email, name


def get_editor_bp(repos: Repositories):
    bp = flask.Blueprint("editor_presence", __name__)
    del repos

    @bp.get("/presence")
    def _list_presence():
        identity = _current_user()
        if identity is None:
            return flask.make_response({"error": "Unauthorized"}, 401)
        users = [s.to_dict() for s in PresenceController.get_all_presence()]
        return flask.jsonify({"users": users})

    @bp.post("/presence/heartbeat")
    def _heartbeat_presence():
        identity = _current_user()
        if identity is None:
            return flask.make_response({"error": "Unauthorized"}, 401)
        email, name = identity

        body = flask.request.get_json(silent=True) or {}
        session_id = body.get("sessionId")
        current_file_path = body.get("currentFilePath")
        if not isinstance(session_id, str):
            return flask.make_response({"error": "sessionId is required"}, 400)
        if current_file_path is not None and not isinstance(current_file_path, str):
            return flask.make_response(
                {"error": "currentFilePath must be a string or null"}, 400
            )

        PresenceController.update_presence(
            session_id=session_id,
            email=email,
            name=name,
            current_file_path=current_file_path,
        )
        return flask.jsonify({"ok": True})

    @bp.post("/presence/leave")
    def _leave_presence():
        identity = _current_user()
        if identity is None:
            return flask.make_response({"error": "Unauthorized"}, 401)

        body = flask.request.get_json(silent=True) or {}
        session_id = body.get("sessionId")
        if not isinstance(session_id, str):
            return flask.make_response({"error": "sessionId is required"}, 400)

        PresenceController.remove_presence(session_id)
        return flask.jsonify({"ok": True})

    return bp
