"""
Mini-projet 02 — API Livres (Flask)
Formation Python Backend

Stockage en mémoire — API REST CRUD complète
Lancer : python app.py
"""

import os
from flask import Flask, Blueprint, request, jsonify, abort

# ── Application ───────────────────────────────────────────
app = Flask(__name__)
API_VERSION = os.getenv("API_VERSION", "1.0")

# ── Données ───────────────────────────────────────────────
_livres: list[dict] = [
    {"id": 1, "titre": "Clean Code",      "auteur": "Robert C. Martin",       "genre": "technique",       "annee": 2008},
    {"id": 2, "titre": "Le Petit Prince", "auteur": "Antoine de Saint-Exupéry","genre": "roman",           "annee": 1943},
    {"id": 3, "titre": "Dune",            "auteur": "Frank Herbert",           "genre": "science-fiction", "annee": 1965},
    {"id": 4, "titre": "Python Fluent",   "auteur": "Luciano Ramalho",         "genre": "technique",       "annee": 2022},
]
_next_id = 5

# ── Helpers ───────────────────────────────────────────────
def find_livre(livre_id: int) -> dict | None:
    return next((l for l in _livres if l["id"] == livre_id), None)

# ── Blueprint ─────────────────────────────────────────────
livres_bp = Blueprint("livres", __name__, url_prefix="/api/livres")

@livres_bp.get("/")
def list_livres():
    genre  = request.args.get("genre")
    auteur = request.args.get("auteur")
    result = _livres
    if genre:
        result = [l for l in result if l.get("genre") == genre]
    if auteur:
        result = [l for l in result if auteur.lower() in l.get("auteur", "").lower()]
    return jsonify({"data": result, "total": len(result)})

@livres_bp.get("/<int:livre_id>")
def get_livre(livre_id: int):
    livre = find_livre(livre_id)
    if livre is None:
        abort(404, description=f"Livre #{livre_id} introuvable")
    return jsonify(livre)

@livres_bp.post("/")
def create_livre():
    global _next_id
    data = request.get_json(silent=True)
    if not data:
        return jsonify({"error": "Body JSON requis"}), 400
    titre  = (data.get("titre")  or "").strip()
    auteur = (data.get("auteur") or "").strip()
    if not titre:
        return jsonify({"error": "Le titre est obligatoire", "field": "titre"}), 400
    if not auteur:
        return jsonify({"error": "L'auteur est obligatoire", "field": "auteur"}), 400
    livre = {
        "id":     _next_id,
        "titre":  titre,
        "auteur": auteur,
        "genre":  (data.get("genre") or "").strip(),
        "annee":  data.get("annee"),
    }
    _livres.append(livre)
    _next_id += 1
    return jsonify(livre), 201

@livres_bp.put("/<int:livre_id>")
def update_livre(livre_id: int):
    livre = find_livre(livre_id)
    if livre is None:
        abort(404, description=f"Livre #{livre_id} introuvable")
    data = request.get_json(silent=True) or {}
    for champ in ("titre", "auteur", "genre", "annee"):
        if champ in data:
            livre[champ] = data[champ]
    return jsonify(livre)

@livres_bp.delete("/<int:livre_id>")
def delete_livre(livre_id: int):
    global _livres
    avant = len(_livres)
    _livres = [l for l in _livres if l["id"] != livre_id]
    if len(_livres) == avant:
        abort(404, description=f"Livre #{livre_id} introuvable")
    return "", 204

# ── Routes globales ───────────────────────────────────────
@app.get("/health")
def health():
    return jsonify({
        "status":  "ok",
        "version": API_VERSION,
        "service": "Bibliothèque API",
        "livres":  len(_livres),
    })

# ── Enregistrement ────────────────────────────────────────
app.register_blueprint(livres_bp)

# ── Gestionnaires d'erreurs ───────────────────────────────
@app.errorhandler(404)
def not_found(e):
    return jsonify({"error": str(e.description), "path": request.path}), 404

@app.errorhandler(400)
def bad_request(e):
    return jsonify({"error": str(e.description)}), 400

@app.errorhandler(405)
def method_not_allowed(e):
    return jsonify({"error": "Méthode HTTP non autorisée"}), 405

@app.errorhandler(500)
def server_error(e):
    return jsonify({"error": "Erreur interne du serveur"}), 500

# ── Démarrage ─────────────────────────────────────────────
if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(debug=os.getenv("FLASK_DEBUG", "1") == "1", port=port)
