import json
from pathlib import Path

from flask import Blueprint, current_app, request
from flask_jwt_extended import jwt_required

from app.extensions import db
from app.models import Recipe
from app.utils.auth import admin_required
from app.utils.response import fail, ok


recipe_bp = Blueprint("recipe", __name__)


def _recipe_payload(recipe: Recipe, payload: dict) -> None:
    recipe.name = payload.get("name", recipe.name)
    recipe.category = payload.get("category", recipe.category or "轻食")
    recipe.description = payload.get("description", recipe.description or "")
    recipe.calories = float(payload.get("calories", recipe.calories or 0))
    recipe.protein = float(payload.get("protein", recipe.protein or 0))
    recipe.fat = float(payload.get("fat", recipe.fat or 0))
    recipe.carbs = float(payload.get("carbs", recipe.carbs or 0))
    recipe.fiber = float(payload.get("fiber", recipe.fiber or 0))
    recipe.tags = payload.get("tags", recipe.tags or [])
    recipe.difficulty = payload.get("difficulty", recipe.difficulty or "easy")


@recipe_bp.get("")
@jwt_required(optional=True)
def list_recipes():
    keyword = (request.args.get("keyword") or "").strip()
    category = (request.args.get("category") or "").strip()
    page = max(int(request.args.get("page", 1) or 1), 1)
    page_size = min(max(int(request.args.get("page_size", 10) or 10), 1), 50)

    query = Recipe.query
    if keyword:
        query = query.filter(Recipe.name.like(f"%{keyword}%"))
    if category:
        query = query.filter(Recipe.category == category)

    pagination = query.order_by(Recipe.id.desc()).paginate(page=page, per_page=page_size, error_out=False)
    data = {
        "items": [item.to_dict() for item in pagination.items],
        "total": pagination.total,
        "page": page,
        "page_size": page_size,
    }
    return ok(data)


@recipe_bp.get("/<int:recipe_id>")
@jwt_required(optional=True)
def get_recipe(recipe_id: int):
    recipe = Recipe.query.get(recipe_id)
    if not recipe:
        return fail("食谱不存在", 404)
    return ok(recipe.to_dict())


@recipe_bp.post("")
@admin_required
def create_recipe():
    payload = request.get_json(silent=True) or {}
    if not payload.get("name"):
        return fail("缺少食谱名称", 400)

    recipe = Recipe()
    _recipe_payload(recipe, payload)

    db.session.add(recipe)
    db.session.commit()
    return ok(recipe.to_dict(), "食谱创建成功")


@recipe_bp.put("/<int:recipe_id>")
@admin_required
def update_recipe(recipe_id: int):
    recipe = Recipe.query.get(recipe_id)
    if not recipe:
        return fail("食谱不存在", 404)

    payload = request.get_json(silent=True) or {}
    _recipe_payload(recipe, payload)
    db.session.commit()
    return ok(recipe.to_dict(), "食谱更新成功")


@recipe_bp.delete("/<int:recipe_id>")
@admin_required
def delete_recipe(recipe_id: int):
    recipe = Recipe.query.get(recipe_id)
    if not recipe:
        return fail("食谱不存在", 404)

    db.session.delete(recipe)
    db.session.commit()
    return ok({}, "食谱删除成功")


@recipe_bp.post("/import")
@admin_required
def import_recipes():
    payload = request.get_json(silent=True) or {}
    rows = payload.get("items")

    if not isinstance(rows, list):
        seed_file = Path(current_app.root_path).parents[0] / "seed" / "recipes_seed.json"
        if seed_file.exists():
            with seed_file.open("r", encoding="utf-8-sig") as file:
                rows = json.load(file)
        else:
            return fail("导入数据为空，且未找到默认种子文件", 400)

    created_count = 0
    updated_count = 0

    for item in rows:
        name = (item.get("name") or "").strip()
        if not name:
            continue

        recipe = Recipe.query.filter_by(name=name).first()
        if recipe:
            _recipe_payload(recipe, item)
            updated_count += 1
        else:
            recipe = Recipe()
            _recipe_payload(recipe, item)
            db.session.add(recipe)
            created_count += 1

    db.session.commit()
    return ok({"created": created_count, "updated": updated_count}, "食谱导入完成")
