"""Maker blueprint - recipe creation and editing."""
import requests as http_requests

from flask import Blueprint, flash, jsonify, redirect, render_template, request, session, url_for
from flask_babel import gettext as _

from blueprints.auth import login_required, role_required
from config import Config
from services.api_client import api_client
from services.file_proxy import proxy_file

maker_bp = Blueprint("maker", __name__, url_prefix="/maker")


# ============================================================================
# PAGINE (GET)
# ============================================================================

@maker_bp.route("/recipes")
@login_required
@role_required("Maker")
def recipe_list():
    """List all recipes with filters."""
    page = request.args.get("page", 1, type=int)
    per_page = request.args.get("per_page", 100, type=int)
    search = request.args.get("search", "", type=str)

    params = {"page": page, "per_page": per_page}
    if search:
        params["search"] = search

    resp = api_client.get("/api/recipes", params=params)

    if isinstance(resp, dict) and resp.get("error"):
        flash(_("Errore nel caricamento delle ricette: %(error)s", error=resp.get("detail", "")), "error")
        recipes = []
        total = 0
        pages = 0
    else:
        recipes = resp.get("items", []) if isinstance(resp, dict) else resp
        total = resp.get("total", 0) if isinstance(resp, dict) else len(recipes)
        pages = resp.get("pages", 1) if isinstance(resp, dict) else 1

    return render_template(
        "maker/recipe_list.html",
        recipes=recipes,
        page=page,
        per_page=per_page,
        total=total,
        pages=pages,
        search=search
    )


@maker_bp.route("/recipes/new")
@login_required
@role_required("Maker")
def recipe_new():
    """Create new recipe."""
    return render_template("maker/recipe_editor.html", recipe=None)


@maker_bp.route("/recipes/<int:recipe_id>/edit")
@login_required
@role_required("Maker")
def recipe_edit(recipe_id: int):
    """Edit existing recipe."""
    # Carica recipe con dettagli completi
    resp = api_client.get(f"/api/recipes/{recipe_id}")

    if resp.get("error"):
        flash(_("Errore nel caricamento della ricetta: %(error)s", error=resp.get("detail", "")), "error")
        return redirect(url_for("maker.recipe_list"))

    recipe = resp

    # Carica anche le versioni
    versions_resp = api_client.get(f"/api/recipes/{recipe_id}/versions")
    if isinstance(versions_resp, list):
        recipe["versions"] = versions_resp
    else:
        recipe["versions"] = []

    return render_template("maker/recipe_editor.html", recipe=recipe)


@maker_bp.route("/recipes/<int:recipe_id>/tasks")
@login_required
@role_required("Maker")
def task_editor(recipe_id: int):
    """Task/subtask editor with tolerances."""
    # Carica recipe con task/subtask
    resp = api_client.get(f"/api/recipes/{recipe_id}")

    if resp.get("error"):
        flash(_("Errore nel caricamento della ricetta: %(error)s", error=resp.get("detail", "")), "error")
        return redirect(url_for("maker.recipe_list"))

    recipe = resp

    # Carica tasks con subtasks
    tasks_resp = api_client.get(f"/api/recipes/{recipe_id}/tasks")
    if isinstance(tasks_resp, list):
        recipe["tasks"] = tasks_resp
    else:
        recipe["tasks"] = []

    return render_template("maker/task_editor.html", recipe=recipe)


@maker_bp.route("/recipes/<int:recipe_id>/tasks/<int:task_id>/drawing")
@login_required
@role_required("Maker")
def task_drawing(recipe_id: int, task_id: int):
    """Annotation editor for a specific task."""
    # Load recipe for breadcrumb context
    recipe_resp = api_client.get(f"/api/recipes/{recipe_id}")
    if recipe_resp.get("error"):
        flash(_("Errore nel caricamento della ricetta: %(error)s", error=recipe_resp.get("detail", "")), "error")
        return redirect(url_for("maker.recipe_list"))

    # Load task details
    task_resp = api_client.get(f"/api/tasks/{task_id}")
    if task_resp.get("error"):
        flash(_("Task non trovato: %(error)s", error=task_resp.get("detail", "")), "error")
        return redirect(url_for("maker.task_editor", recipe_id=recipe_id))

    return render_template(
        "maker/task_drawing.html",
        recipe=recipe_resp,
        task=task_resp,
    )


@maker_bp.route("/recipes/<int:recipe_id>/preview")
@login_required
@role_required("Maker")
def recipe_preview(recipe_id: int):
    """Preview recipe as MeasurementTec would see it."""
    # Carica recipe completo
    resp = api_client.get(f"/api/recipes/{recipe_id}")

    if resp.get("error"):
        flash(_("Errore nel caricamento della ricetta: %(error)s", error=resp.get("detail", "")), "error")
        return redirect(url_for("maker.recipe_list"))

    recipe = resp

    # Carica tasks con subtasks
    tasks_resp = api_client.get(f"/api/recipes/{recipe_id}/tasks")
    if isinstance(tasks_resp, list):
        recipe["tasks"] = tasks_resp
    else:
        recipe["tasks"] = []

    return render_template("maker/recipe_preview.html", recipe=recipe)


@maker_bp.route("/recipes/<int:recipe_id>/versions")
@login_required
@role_required("Maker")
def version_history(recipe_id: int):
    """Version history with diff."""
    # Carica recipe base
    resp = api_client.get(f"/api/recipes/{recipe_id}")

    if resp.get("error"):
        flash(_("Errore nel caricamento della ricetta: %(error)s", error=resp.get("detail", "")), "error")
        return redirect(url_for("maker.recipe_list"))

    recipe = resp

    # Carica versioni
    versions_resp = api_client.get(f"/api/recipes/{recipe_id}/versions")
    if isinstance(versions_resp, list):
        versions = versions_resp
    else:
        versions = []
        flash(_("Errore nel caricamento delle versioni: %(error)s",
               error=versions_resp.get("detail", "") if isinstance(versions_resp, dict) else ""), "warning")

    return render_template("maker/version_history.html", recipe=recipe, versions=versions)


# ============================================================================
# API PROXY AJAX (JSON)
# ============================================================================

@maker_bp.route("/api/recipes", methods=["POST"])
@login_required
@role_required("Maker")
def api_create_recipe():
    """Proxy: Create new recipe."""
    data = request.get_json(silent=True) or {}

    resp = api_client.post("/api/recipes", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 201


@maker_bp.route("/api/recipes/<int:recipe_id>", methods=["PUT"])
@login_required
@role_required("Maker")
def api_update_recipe(recipe_id: int):
    """Proxy: Update recipe (creates new version)."""
    data = request.get_json(silent=True) or {}

    resp = api_client.put(f"/api/recipes/{recipe_id}", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


@maker_bp.route("/api/recipes/<int:recipe_id>", methods=["DELETE"])
@login_required
@role_required("Maker")
def api_delete_recipe(recipe_id: int):
    """Proxy: Delete recipe (soft delete)."""
    resp = api_client.delete(f"/api/recipes/{recipe_id}")

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


# ============================================================================
# TASK API PROXY
# ============================================================================

@maker_bp.route("/api/recipes/<int:recipe_id>/tasks", methods=["POST"])
@login_required
@role_required("Maker")
def api_create_task(recipe_id: int):
    """Proxy: Create new task."""
    data = request.get_json(silent=True) or {}

    resp = api_client.post(f"/api/recipes/{recipe_id}/tasks", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 201


@maker_bp.route("/api/tasks/<int:task_id>", methods=["PUT"])
@login_required
@role_required("Maker")
def api_update_task(task_id: int):
    """Proxy: Update task."""
    data = request.get_json(silent=True) or {}

    resp = api_client.put(f"/api/tasks/{task_id}", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


@maker_bp.route("/api/tasks/<int:task_id>", methods=["DELETE"])
@login_required
@role_required("Maker")
def api_delete_task(task_id: int):
    """Proxy: Delete task."""
    resp = api_client.delete(f"/api/tasks/{task_id}")

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    # 204 No Content returns empty dict
    return jsonify(resp), 204


@maker_bp.route("/api/tasks/reorder", methods=["PUT"])
@login_required
@role_required("Maker")
def api_reorder_tasks():
    """Proxy: Reorder tasks."""
    data = request.get_json(silent=True) or {}

    resp = api_client.put("/api/tasks/reorder", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


# ============================================================================
# SUBTASK API PROXY
# ============================================================================

@maker_bp.route("/api/tasks/<int:task_id>/subtasks", methods=["POST"])
@login_required
@role_required("Maker")
def api_create_subtask(task_id: int):
    """Proxy: Create new subtask."""
    data = request.get_json(silent=True) or {}

    resp = api_client.post(f"/api/tasks/{task_id}/subtasks", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 201


@maker_bp.route("/api/subtasks/<int:subtask_id>", methods=["PUT"])
@login_required
@role_required("Maker")
def api_update_subtask(subtask_id: int):
    """Proxy: Update subtask."""
    data = request.get_json(silent=True) or {}

    resp = api_client.put(f"/api/subtasks/{subtask_id}", data=data)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


@maker_bp.route("/api/subtasks/<int:subtask_id>", methods=["DELETE"])
@login_required
@role_required("Maker")
def api_delete_subtask(subtask_id: int):
    """Proxy: Delete subtask."""
    resp = api_client.delete(f"/api/subtasks/{subtask_id}")

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    # 204 No Content returns empty dict
    return jsonify(resp), 204


# ============================================================================
# FILE API PROXY
# ============================================================================

@maker_bp.route("/api/upload", methods=["POST"])
@login_required
@role_required("Maker")
def api_upload_file():
    """Proxy: Upload file (multipart forward)."""
    # Controlla se c'è un file
    if "file" not in request.files:
        return jsonify({"error": True, "detail": _("Nessun file caricato")}), 400

    file = request.files["file"]
    if file.filename == "":
        return jsonify({"error": True, "detail": _("Nome file vuoto")}), 400

    # Prepara multipart data
    recipe_id = request.form.get("recipe_id")
    version_id = request.form.get("version_id")

    files = {"file": (file.filename, file.stream, file.content_type)}
    data = {}
    if recipe_id:
        data["recipe_id"] = recipe_id
    if version_id:
        data["version_id"] = version_id

    # Forward multipart request
    resp = api_client.post("/api/files/upload", data=data, files=files)

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 201


@maker_bp.route("/api/files/<path:file_path>", methods=["GET"])
@login_required
def api_get_file(file_path: str):
    """Proxy: Serve file from API server (browser can't send X-API-Key)."""
    return proxy_file(file_path)


@maker_bp.route("/api/files/<path:file_path>", methods=["DELETE"])
@login_required
@role_required("Maker")
def api_delete_file(file_path: str):
    """Proxy: Delete file."""
    resp = api_client.delete(f"/api/files/{file_path}")

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    # 204 No Content returns empty dict
    return jsonify(resp), 204


# ============================================================================
# VERSION API PROXY
# ============================================================================

@maker_bp.route("/api/recipes/<int:recipe_id>/versions/<int:version_number>/measurement-count", methods=["GET"])
@login_required
@role_required("Maker")
def api_get_measurement_count(recipe_id: int, version_number: int):
    """Proxy: Get measurement count for a specific version."""
    resp = api_client.get(f"/api/recipes/{recipe_id}/versions/{version_number}/measurement-count")

    if resp.get("error"):
        return jsonify(resp), resp.get("status_code", 500)

    return jsonify(resp), 200


@maker_bp.route("/api/recipes/<int:recipe_id>/parse-technical-sheet", methods=["POST"])
@login_required
@role_required("Maker")
def api_parse_technical_sheet(recipe_id: int):
    """Proxy: Parse PDF technical sheet with AI."""
    file = request.files.get("file")
    if not file:
        return jsonify({"error": True, "detail": "Nessun file caricato"}), 400

    api_key = session.get("api_key", "")
    base_url = Config.API_SERVER_URL.rstrip("/")
    resp = http_requests.post(
        f"{base_url}/api/recipes/{recipe_id}/parse-technical-sheet",
        headers={"X-API-Key": api_key},
        files={"file": (file.filename, file.stream, file.content_type)},
        timeout=90,
    )

    try:
        payload = resp.json()
    except ValueError:
        payload = {
            "error": True,
            "detail": resp.text or f"HTTP {resp.status_code}",
        }
    return jsonify(payload), resp.status_code
