import requests
import logging
import json
from urllib.parse import urlparse
from config import WP_URL, WP_USERNAME, WP_APP_PASSWORD, VALID_CATEGORIES

# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

def get_or_create_tags(tag_names):
    """
    Given a list of tag names, checks if they exist in WordPress.
    If yes, returns their IDs. If no, creates them and returns the new IDs.
    """
    tag_ids = []
    auth = (WP_USERNAME, WP_APP_PASSWORD)
    tags_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/tags"
    
    for name in tag_names:
        name = name.strip()
        if not name:
            continue
        try:
            # Check if tag exists
            response = requests.get(tags_url, params={"search": name}, auth=auth, timeout=10)
            if response.status_code == 200:
                existing_tags = response.json()
                # Double check exact match
                matched = False
                for tag in existing_tags:
                    if tag["name"].lower() == name.lower():
                        tag_ids.append(tag["id"])
                        matched = True
                        break
                
                if matched:
                    continue
            
            # Create tag if it doesn't exist
            create_response = requests.post(tags_url, json={"name": name}, auth=auth, timeout=10)
            if create_response.status_code == 201:
                new_tag = create_response.json()
                tag_ids.append(new_tag["id"])
                logging.info(f"Created new tag in WordPress: {name} (ID: {new_tag['id']})")
            else:
                logging.warning(f"Failed to create tag '{name}': {create_response.text}")
        except Exception as e:
            logging.error(f"Error handling tag '{name}': {e}")
            
    return tag_ids

def get_or_create_category(category_slug):
    """
    Given a category slug, finds or creates the category in WordPress.
    Returns the category ID, or None if it fails.
    """
    if not category_slug or category_slug not in VALID_CATEGORIES:
        category_slug = "latest-news"  # default fallback
    
    auth = (WP_USERNAME, WP_APP_PASSWORD)
    categories_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/categories"
    
    try:
        # Search for existing category by slug
        response = requests.get(categories_url, params={"slug": category_slug}, auth=auth, timeout=10)
        if response.status_code == 200:
            cats = response.json()
            if cats:
                logging.info(f"Found category '{category_slug}' (ID: {cats[0]['id']})")
                return cats[0]["id"]
        
        # Create if not found
        name = category_slug.replace("-", " ").title()
        create_resp = requests.post(categories_url, json={"name": name, "slug": category_slug}, auth=auth, timeout=10)
        if create_resp.status_code == 201:
            new_cat = create_resp.json()
            logging.info(f"Created category '{category_slug}' (ID: {new_cat['id']})")
            return new_cat["id"]
        else:
            logging.warning(f"Failed to create category '{category_slug}': {create_resp.text}")
    except Exception as e:
        logging.error(f"Error handling category '{category_slug}': {e}")
    
    return None

def upload_image_to_wp(image_url, title):
    """
    Downloads an image from a URL and uploads it to the WordPress Media Library.
    If downloading fails, returns None.
    Returns a dict with {'id': media_id, 'url': source_url} if successful, otherwise None.
    """
    if not image_url:
        return None
        
    logging.info(f"Downloading image: {image_url}")
    auth = (WP_USERNAME, WP_APP_PASSWORD)
    media_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/media"
    
    img_content = None
    content_type = "image/jpeg"
    
    try:
        parsed_url = urlparse(image_url)
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
            "Referer": f"{parsed_url.scheme}://{parsed_url.netloc}/"
        }
        img_response = requests.get(image_url, headers=headers, timeout=15)
        img_response.raise_for_status()
        img_content = img_response.content
        content_type = img_response.headers.get("Content-Type", "image/jpeg")
    except Exception as e:
        logging.warning(f"Error downloading original/AI image ({e}). Skipping image.")
        return None

    try:
        # Determine filename and content type
        ext = "jpg"
        if "png" in content_type:
            ext = "png"
        elif "webp" in content_type:
            ext = "webp"
            
        # Clean filename from title (only keeping ASCII characters to prevent Unicode header errors in requests)
        ascii_title = "".join(c for c in title if ('a' <= c.lower() <= 'z') or ('0' <= c <= '9') or c in (" ", "_", "-")).rstrip()
        if not ascii_title.strip():
            import hashlib
            ascii_title = hashlib.md5(title.encode('utf-8')).hexdigest()
        filename = f"{ascii_title.replace(' ', '_').lower()}.{ext}"
        
        # Upload to WordPress media API
        upload_headers = {
            "Content-Type": content_type,
            "Content-Disposition": f'attachment; filename="{filename}"'
        }
        
        logging.info(f"Uploading image to WP Media library as '{filename}'...")
        response = requests.post(
            media_url, 
            headers=upload_headers, 
            data=img_content, 
            auth=auth, 
            timeout=25
        )
        
        if response.status_code == 201:
            res_data = response.json()
            media_id = res_data.get("id")
            source_url = res_data.get("source_url")
            logging.info(f"Successfully uploaded image. Media ID: {media_id}, URL: {source_url}")
            return {"id": media_id, "url": source_url}
        else:
            logging.warning(f"Failed to upload media to WordPress: {response.text}")
            return None
            
    except Exception as e:
        logging.error(f"Error uploading image to WordPress: {e}")
        return None

def post_to_wordpress(article_data, status="draft", featured_image_url=None, body_image_urls=None):
    """
    Posts the rewritten article data to the WordPress site.
    Default status is 'draft' for safety. Set to 'publish' for instant publishing.
    """
    posts_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/posts"
    auth = (WP_USERNAME, WP_APP_PASSWORD)
    
    # Retrieve or create tag IDs
    tag_ids = get_or_create_tags(article_data.get("tags", []))
    
    # Retrieve or create category ID
    category_slug = article_data.get("category", "latest-news")
    category_id = get_or_create_category(category_slug)
    category_ids = [category_id] if category_id else []
    
    # Upload and bind featured image if provided
    featured_media_id = None
    
    # Check if we should generate an image or use the original cover image
    actual_image_url = featured_image_url
    if actual_image_url and "googleusercontent.com" not in actual_image_url:
        upload_res = upload_image_to_wp(actual_image_url, article_data.get("title", "Featured Image"))
        if upload_res:
            featured_media_id = upload_res["id"]
            
    # Process body content and insert extra body images if they can be successfully downloaded
    content_body = article_data.get("content", "")
    
    actual_body_images = list(body_image_urls) if body_image_urls else []
            
    if actual_body_images:
        paragraphs = content_body.split("</p>")
        # Remove empty strings at the end
        if paragraphs and not paragraphs[-1].strip():
            paragraphs.pop()
            
        num_paragraphs = len(paragraphs)
        
        inserted_count = 0
        for idx, img_url in enumerate(actual_body_images[:3]):  # Limit to max 3 body images
            img_res = upload_image_to_wp(img_url, f"{article_data.get('title')} body image {idx+1}")
            if img_res:
                wp_img_url = img_res["url"]
                # Determine slot index: insert after paragraph 2, 4, etc.
                insert_idx = min(2 + (inserted_count * 2), num_paragraphs)
                img_html = f'\n<p class="post-body-image" style="text-align: center; margin: 25px 0;"><img src="{wp_img_url}" alt="{article_data.get("title")}" class="aligncenter size-large" style="max-width: 100%; height: auto; border-radius: 8px;" /></p>\n'
                
                # Insert image block into the paragraph array
                paragraphs.insert(insert_idx, img_html)
                num_paragraphs += 1 # list grew
                inserted_count += 1
                
        # Rebuild content body by joining with </p>
        recombined_content = ""
        for item in paragraphs:
            if item.strip().startswith('<p class="post-body-image"'):
                recombined_content += item # already wrapped in <p>
            else:
                recombined_content += item + "</p>"
        content_body = recombined_content
    
    # Convert script array to standardized JSON string for the WP REST API
    video_script_str = json.dumps(article_data.get("video_script", {}), ensure_ascii=False)
    
    post_payload = {
        "title": article_data.get("title", ""),
        "content": content_body,
        "excerpt": article_data.get("excerpt", ""),
        "status": status,
        "tags": tag_ids,
        "categories": category_ids,
        # Save video script metadata in post meta (registered by our custom plugin)
        "meta": {
            "video_script_json": video_script_str
        }
    }
    
    if featured_media_id:
        post_payload["featured_media"] = featured_media_id
    
    try:
        response = requests.post(posts_url, json=post_payload, auth=auth, timeout=20)
        
        # If meta key is not registered, WP might return 400. 
        # Fallback by removing meta field if it errors out.
        if response.status_code == 400 and "meta" in response.text:
            logging.warning("Post failed with meta fields. Retrying without meta payload...")
            post_payload.pop("meta")
            response = requests.post(posts_url, json=post_payload, auth=auth, timeout=20)
            
        if response.status_code in [200, 201]:
            result = response.json()
            logging.info(f"Successfully posted article to WP: {result.get('link')} (ID: {result.get('id')})")
            return result
        else:
            logging.error(f"Failed to post to WordPress. Status: {response.status_code}, Response: {response.text}")
            return None
            
    except Exception as e:
        logging.error(f"Error posting to WordPress: {e}")
        return None
