"""
WordPress REST API integration for publishing articles.
Handles media upload, post creation, and Yoast SEO metadata.
"""

import logging
import mimetypes
from dataclasses import dataclass
from pathlib import Path
from typing import Optional

import requests

from config.settings import get_settings
from database.models import Article, ArticleRepository

logger = logging.getLogger(__name__)


@dataclass
class PublishResult:
    success: bool
    wp_post_id: Optional[int] = None
    wp_media_id: Optional[int] = None
    post_url: Optional[str] = None
    error: Optional[str] = None


class WordPressClient:
    """WordPress REST API client."""

    def __init__(self):
        settings = get_settings()
        self.base_url = settings.wp_url.rstrip("/")
        self.api_url = f"{self.base_url}/wp-json/wp/v2"
        self.auth = settings.wp_auth
        self._authors_cache = None

    def _request(
        self,
        method: str,
        endpoint: str,
        data: Optional[dict] = None,
        files: Optional[dict] = None,
    ) -> requests.Response:
        """Make authenticated request to WP REST API."""
        url = f"{self.api_url}/{endpoint}"
        response = requests.request(
            method,
            url,
            auth=self.auth,
            json=data if method != "POST" or not files else None,
            data=data if files else None,
            files=files,
            timeout=60,
        )
        return response

    def get_authors(self) -> list[dict]:
        """Get all users for author rotation."""
        if self._authors_cache is not None:
            return self._authors_cache

        try:
            response = self._request("GET", "users?per_page=100")
            response.raise_for_status()
            self._authors_cache = response.json()
            return self._authors_cache
        except Exception as e:
            logger.error(f"Failed to fetch authors: {e}")
            return []

    def get_next_author_id(self) -> int:
        """Get next author ID using round-robin rotation."""
        authors = self.get_authors()
        if not authors:
            logger.warning("No authors found, using default author 1")
            return 1

        # Get last published article's author
        last_article = ArticleRepository.get_last_published()
        if last_article and last_article.author_id:
            # Find current author's index
            author_ids = [a["id"] for a in authors]
            try:
                current_idx = author_ids.index(last_article.author_id)
                next_idx = (current_idx + 1) % len(authors)
            except ValueError:
                next_idx = 0
        else:
            next_idx = 0

        next_author = authors[next_idx]
        logger.info(f"Selected author: {next_author.get('name', next_author['id'])}")
        return next_author["id"]

    def get_category_id(self, category_slug: str) -> Optional[int]:
        """Get category ID by slug."""
        try:
            response = self._request("GET", f"categories?slug={category_slug}")
            response.raise_for_status()
            categories = response.json()
            if categories:
                return categories[0]["id"]
            return None
        except Exception as e:
            logger.error(f"Failed to fetch category: {e}")
            return None

    def upload_media(self, file_path: str, title: str = "") -> Optional[int]:
        """
        Upload image to WordPress Media Library.

        Returns media ID on success, None on failure.
        """
        path = Path(file_path)
        if not path.exists():
            logger.error(f"File not found: {file_path}")
            return None

        mime_type = mimetypes.guess_type(file_path)[0] or "image/webp"
        filename = path.name

        try:
            with open(file_path, "rb") as f:
                response = requests.post(
                    f"{self.api_url}/media",
                    auth=self.auth,
                    headers={
                        "Content-Disposition": f'attachment; filename="{filename}"',
                        "Content-Type": mime_type,
                    },
                    data=f.read(),
                    timeout=120,
                )

            response.raise_for_status()
            media = response.json()
            media_id = media["id"]
            logger.info(f"Uploaded media: ID={media_id}, file={filename}")

            # Update alt text if title provided
            if title:
                self._request(
                    "POST",
                    f"media/{media_id}",
                    data={"alt_text": title, "title": title},
                )

            return media_id

        except Exception as e:
            logger.error(f"Media upload failed: {e}")
            return None

    def create_post(
        self,
        title: str,
        content_html: str,
        slug: str,
        meta_description: str,
        author_id: int,
        category_ids: list[int],
        featured_media_id: Optional[int] = None,
        status: str = "publish",
    ) -> PublishResult:
        """
        Create a new WordPress post with Yoast SEO metadata.
        """
        post_data = {
            "title": title,
            "content": content_html,
            "slug": slug,
            "status": status,
            "author": author_id,
            "categories": category_ids,
            "comment_status": "open",
            "ping_status": "open",
        }

        if featured_media_id:
            post_data["featured_media"] = featured_media_id

        # Yoast SEO metadata (requires Yoast REST API extension)
        post_data["meta"] = {
            "_yoast_wpseo_metadesc": meta_description[:155],
            "_yoast_wpseo_focuskw": "",  # Will be set from keywords if needed
        }

        try:
            response = self._request("POST", "posts", data=post_data)
            response.raise_for_status()
            post = response.json()

            post_id = post["id"]
            post_url = post.get("link", "")

            logger.info(f"Created post: ID={post_id}, URL={post_url}")

            return PublishResult(
                success=True,
                wp_post_id=post_id,
                wp_media_id=featured_media_id,
                post_url=post_url,
            )

        except requests.exceptions.HTTPError as e:
            error_msg = str(e)
            try:
                error_data = e.response.json()
                error_msg = error_data.get("message", str(e))
            except Exception:
                pass
            logger.error(f"Post creation failed: {error_msg}")
            return PublishResult(success=False, error=error_msg)

        except Exception as e:
            logger.error(f"Post creation failed: {e}")
            return PublishResult(success=False, error=str(e))

    def update_yoast_meta(
        self,
        post_id: int,
        focus_keyword: str = "",
        meta_description: str = "",
    ) -> bool:
        """Update Yoast SEO metadata for existing post."""
        try:
            response = self._request(
                "POST",
                f"posts/{post_id}",
                data={
                    "meta": {
                        "_yoast_wpseo_metadesc": meta_description[:155],
                        "_yoast_wpseo_focuskw": focus_keyword,
                    }
                },
            )
            response.raise_for_status()
            return True
        except Exception as e:
            logger.error(f"Yoast meta update failed: {e}")
            return False


def publish_article(
    article: Article,
    thumbnail_path: Optional[str] = None,
    category_slug: str = "blog",
) -> PublishResult:
    """
    Publish article to WordPress.

    Args:
        article: Article model with content
        thumbnail_path: Path to thumbnail image
        category_slug: WordPress category slug

    Returns:
        PublishResult with post details
    """
    client = WordPressClient()

    # Get author (round-robin)
    author_id = client.get_next_author_id()

    # Get category
    category_id = client.get_category_id(category_slug)
    category_ids = [category_id] if category_id else []

    # Upload thumbnail if provided
    media_id = None
    if thumbnail_path:
        media_id = client.upload_media(thumbnail_path, article.title)

    # Create post
    result = client.create_post(
        title=article.title,
        content_html=article.content_html,
        slug=article.slug,
        meta_description=article.meta_description,
        author_id=author_id,
        category_ids=category_ids,
        featured_media_id=media_id,
    )

    return result
