#!/usr/bin/env python3
"""Enrich recipes with images and descriptions from Spoonacular.

Reads SPOONACULAR_API_KEY and DATABASE_URL from environment.

Run inside the backend container:
  docker cp scripts/enrich_recipes_spoonacular.py mealplanner-backend-1:/app/
  docker compose --env-file .env.test exec backend python /app/enrich_recipes_spoonacular.py
"""
from __future__ import annotations

import os
import re
import time
import logging
import sys

import requests
from sqlalchemy import create_engine, text

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
log = logging.getLogger(__name__)

SPOONACULAR_KEY = os.environ.get("SPOONACULAR_API_KEY", "")
DATABASE_URL = os.environ["DATABASE_URL"]
SEARCH_URL = "https://api.spoonacular.com/recipes/complexSearch"
RATE_LIMIT_SECONDS = 0.5  # 2 req/s — well under 150/day free tier limit


def strip_html(raw: str) -> str:
    return re.sub(r"<[^>]+>", "", raw or "").strip()


def search_recipe(name: str) -> dict | None:
    resp = requests.get(
        SEARCH_URL,
        params={
            "query": name,
            "number": 3,
            "addRecipeInformation": True,
            "apiKey": SPOONACULAR_KEY,
        },
        timeout=30,
    )
    if resp.status_code == 402:
        log.error("Spoonacular quota exhausted — stop and retry tomorrow.")
        sys.exit(1)
    resp.raise_for_status()
    results = resp.json().get("results", [])
    return results[0] if results else None


def main() -> None:
    if not SPOONACULAR_KEY:
        log.error("SPOONACULAR_API_KEY not set")
        sys.exit(1)

    engine = create_engine(DATABASE_URL)

    with engine.connect() as conn:
        recipes = conn.execute(
            text(
                "SELECT id, name, image_url, description "
                "FROM recipe "
                "WHERE image_url IS NULL OR description IS NULL "
                "ORDER BY name"
            )
        ).fetchall()

    log.info("Recipes to enrich: %d", len(recipes))

    updated = 0
    no_match = 0

    engine2 = create_engine(DATABASE_URL)
    with engine2.connect() as conn:
        for recipe_id, name, existing_image, existing_desc in recipes:
            log.info("[%d/%d] %s", updated + no_match + 1, len(recipes), name)

            try:
                match = search_recipe(name)
            except requests.RequestException as exc:
                log.warning("  API error: %s — skipping", exc)
                time.sleep(2)
                continue

            if not match:
                log.info("  no Spoonacular match")
                no_match += 1
                time.sleep(RATE_LIMIT_SECONDS)
                continue

            new_image = existing_image or match.get("image") or None
            raw_summary = match.get("summary", "")
            new_desc = existing_desc or (strip_html(raw_summary) or None)

            conn.execute(
                text(
                    "UPDATE recipe SET image_url = :img, description = :desc WHERE id = :id"
                ),
                {"img": new_image, "desc": new_desc, "id": recipe_id},
            )
            conn.commit()

            img_ok = "✓" if new_image else "—"
            desc_len = len(new_desc) if new_desc else 0
            log.info("  image=%s  desc=%d chars", img_ok, desc_len)
            updated += 1
            time.sleep(RATE_LIMIT_SECONDS)

    log.info(
        "Done — updated: %d  no-match: %d  already-complete: %d",
        updated,
        no_match,
        len(recipes) - updated - no_match,
    )


if __name__ == "__main__":
    main()
