"""
Marziel AI — Embedded LLM Routes.

Registers Marziel-native and backward-compatible API endpoints
on the Flask server. All inference is routed through the MarzielEngine
(in-process, no subprocess or HTTP calls).

Endpoints:
    /marziel/v1/infer    — Marziel-native inference API
    /marziel/v1/models   — Engine & model status
    /v1/models           — Backward-compat (OpenAI format)
    /v1/chat/completions — Backward-compat (OpenAI format)
"""

import json
import logging
import os
import time

logger = logging.getLogger("marziel.llm_embedded")


def load_model(model_dir: str = None) -> bool:
    """
    Load the model via MarzielEngine (backward-compatible entry point).

    Called by server.py on startup in a background thread.
    """
    from marziel.engine import get_engine

    engine = get_engine(model_dir=model_dir)
    return engine.load()


def register_routes(app):
    """Register Marziel-native and backward-compatible routes on the Flask app."""
    from flask import request, jsonify
    from marziel.engine import get_engine

    # ── Marziel-Native API ──────────────────────────────────

    @app.route("/marziel/v1/infer", methods=["POST", "OPTIONS"])
    def marziel_infer():
        """
        Marziel-native inference endpoint.

        Request:
            {
                "prompt": "Hello!",
                "history": [{"role": "user", "content": "..."}],
                "system_prompt": "optional override",
                "temperature": 0.7,
                "max_tokens": 1024
            }

        Response:
            {
                "text": "...",
                "tokens_used": 87,
                "duration_ms": 412.3,
                "tokens_per_sec": 34.2,
                "engine": "marziel-engine",
                "hardware": "cuda",
                "model": "marziel-v6-Q4_K_M",
                "turboquant": {"active": true, ...}
            }
        """
        if request.method == "OPTIONS":
            return "", 204

        engine = get_engine()
        if not engine.is_ready:
            engine.load()

        data = request.get_json(force=True)
        prompt = data.get("prompt", "")
        if not prompt:
            return jsonify({"error": "No prompt provided"}), 400

        result = engine.infer(
            prompt=prompt,
            history=data.get("history", []),
            system_prompt=data.get("system_prompt"),
            temperature=data.get("temperature", 0.7),
            max_tokens=data.get("max_tokens", 1024),
            stop=data.get("stop"),
        )

        if "error" in result and result["error"]:
            return jsonify(result), 503

        return jsonify(result)

    @app.route("/marziel/v1/models", methods=["GET"])
    def marziel_models():
        """Engine status and model info."""
        engine = get_engine()
        return jsonify(engine.get_status())

    # ── Backward-Compatible OpenAI API ──────────────────────

    @app.route("/v1/models", methods=["GET"])
    def v1_models():
        """OpenAI-compatible model listing (backward compat)."""
        engine = get_engine()
        info = engine.get_model_info()
        if info["status"] != "ready":
            return jsonify({"data": []})
        return jsonify({
            "data": [{
                "id": info["model"],
                "object": "model",
                "owned_by": "marziel",
            }]
        })

    @app.route("/v1/chat/completions", methods=["POST", "OPTIONS"])
    def v1_chat_completions():
        """
        OpenAI-compatible chat completions (backward compat).

        Translates OpenAI format to/from MarzielEngine and back.
        Kept for external tools and react_agent compatibility.
        """
        if request.method == "OPTIONS":
            return "", 200

        engine = get_engine()
        if not engine.is_ready:
            engine.load()
        if not engine.is_ready:
            return jsonify({"error": "Model not loaded"}), 503

        data = request.get_json(force=True)
        messages = data.get("messages", [])
        temperature = data.get("temperature", 0.7)
        max_tokens = data.get("max_tokens", 2048)
        stop = data.get("stop", [])

        # Use raw inference (caller already built messages)
        result = engine.infer_raw(
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens,
            stop=stop,
        )

        if "error" in result and result["error"]:
            return jsonify({"error": result["error"]}), 500

        # If we have the raw llama-cpp-python response, return it directly
        if "raw" in result and result["raw"]:
            return jsonify(result["raw"])

        # Otherwise build an OpenAI-shaped response
        return jsonify({
            "id": f"marziel-{int(time.time())}",
            "object": "chat.completion",
            "created": int(time.time()),
            "model": engine._model_id,
            "choices": [{
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": result.get("text", ""),
                },
                "finish_reason": "stop",
            }],
            "usage": {
                "prompt_tokens": 0,
                "completion_tokens": 0,
                "total_tokens": 0,
            },
        })

    logger.info(
        "📡 Marziel Engine routes registered "
        "(/marziel/v1/infer + /v1/chat/completions)"
    )
