"""
AI Rewriter + Blog Poster
=========================
1. Takes a raw article dict
2. Rewrites it via Ollama (category-specific prompt)
3. Posts the rewritten article to WordPress via REST API

Usage (standalone test):
    python3 ai_rewriter.py
"""

import json
import logging
import re
import requests
from typing import Optional

from prompts import get_prompt
from config import CRAWLER_CONFIG

log = logging.getLogger(__name__)

# ── Ollama ─────────────────────────────────────────────────────────────────────

def rewrite_article(article: dict) -> dict:
    """
    Rewrite the article content using Ollama.
    Returns the article dict with 'content' and 'excerpt' replaced.
    Original content is preserved under 'original_content'.
    """
    ollama  = CRAWLER_CONFIG["ollama"]
    url     = ollama["url"]
    model   = ollama["model"]
    title   = article["title"]
    content = article["content"]
    category = article["category"]

    if not content:
        log.warning("[%s] Skipping rewrite — no content", title[:60])
        return article

    prompt = get_prompt(category, title, content)

    log.info("  Rewriting [%s] via Ollama (%s)...", category, model)
    log.debug("  Prompt length: %d chars", len(prompt))

    try:
        resp = requests.post(
            url,
            json={
                "model":  model,
                "prompt": prompt,
                "stream": False,
                "options": {
                    "temperature": 0.7,   # balanced creativity vs accuracy
                    "num_predict": 1024,  # max output tokens
                },
            },
            timeout=120,
        )
        resp.raise_for_status()
        rewritten = resp.json().get("response", "").strip()

        if not rewritten:
            log.warning("  Ollama returned empty response — using original")
            return article

        original_len  = len(content)
        rewritten_len = len(rewritten)
        log.info("  Rewrite OK: %d chars → %d chars", original_len, rewritten_len)

        article = article.copy()
        article["original_content"] = content
        article["content"]  = rewritten
        article["excerpt"]  = (rewritten[:300] + "...") if len(rewritten) > 300 else rewritten
        article["rewritten"] = True
        return article

    except requests.ConnectionError:
        log.error("  Ollama not reachable at %s — check your VPS / ollama serve", url)
    except requests.Timeout:
        log.error("  Ollama timed out (120s) — model may be too large or VPS overloaded")
    except Exception as exc:
        log.error("  Ollama rewrite failed: %s", exc)

    article["rewritten"] = False
    return article


# ── WordPress poster ────────────────────────────────────────────────────────────

_wp_term_cache: dict = {}

def _get_or_create_term(wp: dict, taxonomy: str, name: str) -> Optional[int]:
    """Look up or create a WordPress category or tag by name."""
    key = f"{taxonomy}:{name}"
    if key in _wp_term_cache:
        return _wp_term_cache[key]

    base = wp["url"].rstrip("/") + f"/wp-json/wp/v2/{taxonomy}"
    auth = (wp["username"], wp["app_password"])
    try:
        r = requests.get(base, params={"search": name, "per_page": 5}, auth=auth, timeout=10)
        r.raise_for_status()
        hits = r.json()
        if hits:
            tid = hits[0]["id"]
            _wp_term_cache[key] = tid
            return tid
        # create it
        r = requests.post(base, json={"name": name}, auth=auth, timeout=10)
        r.raise_for_status()
        tid = r.json()["id"]
        _wp_term_cache[key] = tid
        log.debug("  Created WP term: %s → id=%s", name, tid)
        return tid
    except Exception as exc:
        log.warning("  Could not get/create WP term '%s': %s", name, exc)
    return None


def _upload_featured_image(wp: dict, post_id: int, image_url: str, title: str) -> None:
    """Download image from URL and set it as the post's featured image."""
    try:
        img = requests.get(image_url, timeout=10)
        img.raise_for_status()

        content_type = img.headers.get("content-type", "image/jpeg").split(";")[0]
        ext = content_type.split("/")[-1] or "jpg"
        filename = re.sub(r"[^\w]", "_", title[:40]) + f".{ext}"

        media_url = wp["url"].rstrip("/") + "/wp-json/wp/v2/media"
        up = requests.post(
            media_url,
            data=img.content,
            headers={
                "Content-Disposition": f'attachment; filename="{filename}"',
                "Content-Type": content_type,
            },
            auth=(wp["username"], wp["app_password"]),
            timeout=30,
        )
        up.raise_for_status()
        media_id = up.json()["id"]

        requests.post(
            wp["url"].rstrip("/") + f"/wp-json/wp/v2/posts/{post_id}",
            json={"featured_media": media_id},
            auth=(wp["username"], wp["app_password"]),
            timeout=10,
        ).raise_for_status()

        log.info("  Featured image set (media_id=%s)", media_id)
    except Exception as exc:
        log.warning("  Could not set featured image: %s", exc)


def post_to_wordpress(article: dict) -> Optional[int]:
    """
    Post a single (already rewritten) article to WordPress.
    Returns the new post ID, or None on failure.
    """
    wp = CRAWLER_CONFIG["wordpress"]
    if not wp.get("url") or wp["url"].startswith("https://your-"):
        log.error("WordPress not configured in config.py")
        return None

    api_url = wp["url"].rstrip("/") + "/wp-json/wp/v2/posts"
    auth    = (wp["username"], wp["app_password"])

    # Resolve category and tags
    cat_id  = _get_or_create_term(wp, "categories", article["category"])
    tag_ids = [_get_or_create_term(wp, "tags", t) for t in article.get("tags", [])]

    payload = {
        "title":      article["title"],
        "content":    article["content"],
        "excerpt":    article.get("excerpt", ""),
        "status":     wp.get("post_status", "draft"),
        "categories": [cat_id] if cat_id else [],
        "tags":       [tid for tid in tag_ids if tid],
        "meta": {
            "source_name": article.get("source", ""),
            "source_url":  article.get("source_url", ""),
            "continent":   article.get("continent", ""),
            "country":     article.get("country", ""),
            "crawled_at":  article.get("crawled_at", ""),
        },
    }

    try:
        r = requests.post(api_url, json=payload, auth=auth, timeout=20)
        r.raise_for_status()
        post_id = r.json()["id"]
        log.info("  Posted to WP → id=%s | %s", post_id, article["title"][:70])

        if article.get("image_url") and post_id:
            _upload_featured_image(wp, post_id, article["image_url"], article["title"])

        return post_id

    except requests.HTTPError as exc:
        log.error("  WP post failed: %s — %s", exc, getattr(r, "text", "")[:200])
    except Exception as exc:
        log.error("  WP post error: %s", exc)
    return None


# ── Full pipeline ───────────────────────────────────────────────────────────────

def process_article(article: dict, post: bool = False) -> dict:
    """
    Full pipeline for one article:
      1. Rewrite with Ollama (category-specific prompt)
      2. Optionally post to WordPress

    Returns the processed article dict with added fields:
      - rewritten (bool)
      - wp_post_id (int or None)
    """
    # Step 1: AI rewrite
    article = rewrite_article(article)

    # Step 2: Post to WordPress
    if post:
        wp_id = post_to_wordpress(article)
        article["wp_post_id"] = wp_id
    else:
        article["wp_post_id"] = None

    return article


# ── Standalone test ─────────────────────────────────────────────────────────────

if __name__ == "__main__":
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)-8s] %(message)s",
    )

    # Load articles from the test output and run one through the pipeline
    import sys
    source_file = sys.argv[1] if len(sys.argv) > 1 else "test_output.json"

    try:
        with open(source_file) as f:
            articles = json.load(f)
    except FileNotFoundError:
        print(f"Run test_crawl.py first to generate {source_file}")
        sys.exit(1)

    print(f"\nLoaded {len(articles)} articles from {source_file}")
    print("Testing rewrite pipeline — one article per category...\n")

    seen_categories = set()
    for article in articles:
        cat = article["category"]
        if cat in seen_categories:
            continue
        seen_categories.add(cat)

        print(f"{'─'*60}")
        print(f"Category : {cat}")
        print(f"Source   : {article['source']} ({article['country']})")
        print(f"Title    : {article['title']}")
        print(f"Image    : {article['image_url'] or 'MISSING'}")
        print()

        result = process_article(article, post=False)  # post=False → dry run

        if result.get("rewritten"):
            print(f"REWRITTEN CONTENT:\n{result['content'][:600]}...")
        else:
            print("⚠ Rewrite skipped (Ollama unavailable or error)")
        print()
