"""
Memory Feedback REST API Blueprint

PRD §15 — API Design:
    POST /feedback/store          — Write a feedback record (§15.1)
    GET  /feedback/quality        — Query memory quality profile (§15.2)
    GET  /feedback/workflow       — Query workflow quality (§15.3)
    POST /feedback/recall         — Record recall signal
    POST /feedback/inject         — Record injection signal
    POST /feedback/adopt          — Record adoption signal
    POST /feedback/outcome        — Record outcome signal
    GET  /feedback/noisy          — List high-noise memories
    GET  /feedback/adjust         — Adjust a list of recall results
"""

import time
import logging
from flask import Blueprint, request, jsonify
from openmemo.memory_feedback import MemoryFeedback

logger = logging.getLogger("openmemo.feedback.api")


def create_feedback_blueprint(db_path: str = "openmemo.db") -> Blueprint:
    bp = Blueprint("memory_feedback", __name__)
    fb = MemoryFeedback(db_path=db_path)

    # ── POST /feedback/store ──────────────────────────────────────────────────
    @bp.route("/feedback/store", methods=["POST"])
    def store_feedback():
        """
        PRD §15.1 — Write a unified feedback record.

        Body: { "memory_id": "...", "task_id": "...", "agent_id": "...",
                "recalled": bool, "injected": bool, "adopted": bool,
                "success": bool, "token_size": int, "position": "..." }
        """
        body = request.get_json(silent=True) or {}
        memory_id = body.get("memory_id", "").strip()
        if not memory_id:
            return jsonify({"error": "memory_id required"}), 400

        t0 = time.time()
        task_id = body.get("task_id", "")
        agent_id = body.get("agent_id", "")
        recalled = bool(body.get("recalled", False))
        injected = bool(body.get("injected", False))
        adopted = bool(body.get("adopted", False))
        success = bool(body.get("success", False))

        ids = []
        if recalled:
            ids += fb.on_recall([memory_id], task_id=task_id, agent_id=agent_id)
        if injected:
            fb.on_inject(memory_id, task_id=task_id,
                          token_size=body.get("token_size", 0),
                          position=body.get("position", ""),
                          agent_id=agent_id)
        if adopted or success:
            fb.on_adopt(task_id, memory_id=memory_id, adopted=adopted,
                         agent_id=agent_id)
        if success:
            fb.on_outcome(task_id, success=True, memory_ids=[memory_id],
                           agent_id=agent_id)

        profile = fb.get_quality_profile(memory_id)
        return jsonify({
            "status": "recorded",
            "memory_id": memory_id,
            "quality_score": profile.quality_score,
            "latency_ms": round((time.time() - t0) * 1000, 1),
        }), 201

    # ── POST /feedback/recall ──────────────────────────────────────────────────
    @bp.route("/feedback/recall", methods=["POST"])
    def record_recall():
        body = request.get_json(silent=True) or {}
        memory_ids = body.get("memory_ids", [])
        task_id = body.get("task_id", "")
        if not memory_ids:
            return jsonify({"error": "memory_ids required"}), 400
        t0 = time.time()
        ids = fb.on_recall(memory_ids, task_id=task_id,
                            agent_id=body.get("agent_id", ""),
                            memory_layer=body.get("memory_layer", ""))
        return jsonify({"status": "recorded", "feedback_ids": ids,
                         "latency_ms": round((time.time() - t0) * 1000, 1)}), 201

    # ── POST /feedback/inject ──────────────────────────────────────────────────
    @bp.route("/feedback/inject", methods=["POST"])
    def record_inject():
        body = request.get_json(silent=True) or {}
        memory_id = body.get("memory_id", "").strip()
        if not memory_id:
            return jsonify({"error": "memory_id required"}), 400
        t0 = time.time()
        fid = fb.on_inject(memory_id, task_id=body.get("task_id", ""),
                            token_size=body.get("token_size", 0),
                            position=body.get("position", ""),
                            agent_id=body.get("agent_id", ""))
        return jsonify({"status": "recorded", "feedback_id": fid,
                         "latency_ms": round((time.time() - t0) * 1000, 1)}), 201

    # ── POST /feedback/adopt ───────────────────────────────────────────────────
    @bp.route("/feedback/adopt", methods=["POST"])
    def record_adopt():
        body = request.get_json(silent=True) or {}
        task_id = body.get("task_id", "")
        t0 = time.time()
        fid = fb.on_adopt(task_id,
                           memory_id=body.get("memory_id", ""),
                           workflow_id=body.get("workflow_id", ""),
                           adopted=bool(body.get("adopted", False)),
                           adoption_rate=float(body.get("adoption_rate", 0.0)),
                           agent_id=body.get("agent_id", ""))
        return jsonify({"status": "recorded", "feedback_id": fid,
                         "latency_ms": round((time.time() - t0) * 1000, 1)}), 201

    # ── POST /feedback/outcome ─────────────────────────────────────────────────
    @bp.route("/feedback/outcome", methods=["POST"])
    def record_outcome():
        body = request.get_json(silent=True) or {}
        task_id = body.get("task_id", "")
        if not task_id:
            return jsonify({"error": "task_id required"}), 400
        t0 = time.time()
        ids = fb.on_outcome(task_id,
                             success=bool(body.get("success", False)),
                             memory_ids=body.get("memory_ids", []),
                             workflow_id=body.get("workflow_id", ""),
                             execution_time=float(body.get("execution_time", 0)),
                             agent_id=body.get("agent_id", ""))
        return jsonify({"status": "recorded", "feedback_ids": ids,
                         "latency_ms": round((time.time() - t0) * 1000, 1)}), 201

    # ── GET /feedback/quality ─────────────────────────────────────────────────
    @bp.route("/feedback/quality", methods=["GET"])
    def get_quality():
        """PRD §15.2 — Query memory quality profile."""
        memory_id = request.args.get("memory_id", "").strip()
        if not memory_id:
            return jsonify({"error": "memory_id required"}), 400
        t0 = time.time()
        profile = fb.get_quality_profile(memory_id)
        data = profile.to_dict()
        data["latency_ms"] = round((time.time() - t0) * 1000, 1)
        return jsonify(data)

    # ── GET /feedback/workflow ────────────────────────────────────────────────
    @bp.route("/feedback/workflow", methods=["GET"])
    def get_workflow_quality():
        """PRD §15.3 — Query workflow quality scores."""
        workflow_id = request.args.get("workflow_id", "").strip()
        if not workflow_id:
            return jsonify({"error": "workflow_id required"}), 400
        t0 = time.time()
        data = fb.get_workflow_quality(workflow_id)
        data["latency_ms"] = round((time.time() - t0) * 1000, 1)
        return jsonify(data)

    # ── GET /feedback/noisy ───────────────────────────────────────────────────
    @bp.route("/feedback/noisy", methods=["GET"])
    def get_noisy():
        """List high-noise memories (recalled but rarely adopted)."""
        min_noise = int(request.args.get("min_noise", 3))
        profiles = fb.list_noisy_memories(min_noise=min_noise)
        return jsonify({
            "noisy_memories": [p.to_dict() for p in profiles],
            "count": len(profiles),
        })

    return bp
