#!/usr/bin/env python3
"""
Ghost CMS Publisher for OurDigital Blog

Publishes markdown content to Ghost CMS via Admin API.

Usage:
    python ghost_publish.py --file post.md --draft
    python ghost_publish.py --file post.md --publish
"""

import argparse
import os
import re
import jwt
import time
import requests
from datetime import datetime
from pathlib import Path
from dotenv import load_dotenv

# Load environment variables
load_dotenv(os.path.expanduser("~/.env.ourdigital"))


def create_ghost_token(admin_key: str) -> str:
    """Create JWT token for Ghost Admin API."""
    key_id, secret = admin_key.split(":")

    iat = int(time.time())
    header = {"alg": "HS256", "typ": "JWT", "kid": key_id}
    payload = {
        "iat": iat,
        "exp": iat + 5 * 60,  # 5 minutes
        "aud": "/admin/"
    }

    token = jwt.encode(payload, bytes.fromhex(secret), algorithm="HS256", headers=header)
    return token


def parse_frontmatter(content: str) -> tuple[dict, str]:
    """Parse YAML frontmatter from markdown content."""
    import yaml

    pattern = r'^---\s*\n(.*?)\n---\s*\n(.*)$'
    match = re.match(pattern, content, re.DOTALL)

    if match:
        frontmatter = yaml.safe_load(match.group(1))
        body = match.group(2)
        return frontmatter, body

    return {}, content


def publish_to_ghost(
    file_path: str,
    ghost_url: str,
    admin_key: str,
    draft: bool = True
) -> dict:
    """Publish markdown file to Ghost CMS."""

    # Read and parse file
    content = Path(file_path).read_text(encoding="utf-8")
    frontmatter, body = parse_frontmatter(content)

    # Create JWT token
    token = create_ghost_token(admin_key)

    # Prepare post data
    post_data = {
        "posts": [{
            "title": frontmatter.get("title", "Untitled"),
            "slug": frontmatter.get("slug"),
            "html": markdown_to_html(body),
            "meta_description": frontmatter.get("meta_description", ""),
            "tags": [{"name": tag} for tag in frontmatter.get("tags", [])],
            "status": "draft" if draft else "published",
            "authors": [{"email": "andrew.yim@ourdigital.org"}]
        }]
    }

    # Add feature image if provided
    if frontmatter.get("featured_image"):
        post_data["posts"][0]["feature_image"] = frontmatter["featured_image"]

    # Make API request
    api_url = f"{ghost_url}/ghost/api/admin/posts/"
    headers = {
        "Authorization": f"Ghost {token}",
        "Content-Type": "application/json"
    }

    response = requests.post(api_url, json=post_data, headers=headers)
    response.raise_for_status()

    return response.json()


def markdown_to_html(markdown_text: str) -> str:
    """Convert markdown to HTML."""
    try:
        import markdown
        return markdown.markdown(
            markdown_text,
            extensions=["tables", "fenced_code", "codehilite"]
        )
    except ImportError:
        # Basic conversion if markdown library not available
        html = markdown_text.replace("\n\n", "</p><p>")
        html = f"<p>{html}</p>"
        return html


def main():
    parser = argparse.ArgumentParser(description="Publish to Ghost CMS")
    parser.add_argument("--file", required=True, help="Markdown file to publish")
    parser.add_argument("--draft", action="store_true", help="Publish as draft")
    parser.add_argument("--publish", action="store_true", help="Publish immediately")
    parser.add_argument("--channel", default="blog",
                        choices=["blog", "journal", "ourstory"],
                        help="Ghost channel to publish to")

    args = parser.parse_args()

    # Get credentials based on channel
    channel_map = {
        "blog": ("GHOST_BLOG_URL", "GHOST_BLOG_ADMIN_KEY"),
        "journal": ("GHOST_JOURNAL_URL", "GHOST_JOURNAL_ADMIN_KEY"),
        "ourstory": ("GHOST_OURSTORY_URL", "GHOST_OURSTORY_ADMIN_KEY")
    }

    url_var, key_var = channel_map[args.channel]
    ghost_url = os.getenv(url_var)
    admin_key = os.getenv(key_var)

    if not ghost_url or not admin_key:
        print(f"Error: Missing credentials for {args.channel}")
        print(f"Set {url_var} and {key_var} in ~/.env.ourdigital")
        return 1

    try:
        result = publish_to_ghost(
            args.file,
            ghost_url,
            admin_key,
            draft=not args.publish
        )

        post = result["posts"][0]
        status = "Draft" if not args.publish else "Published"
        print(f"{status}: {post['title']}")
        print(f"URL: {ghost_url}/{post['slug']}/")
        print(f"Edit: {ghost_url}/ghost/#/editor/post/{post['id']}")

        return 0

    except Exception as e:
        print(f"Error: {e}")
        return 1


if __name__ == "__main__":
    exit(main())
