from __future__ import annotations

import base64
import json
import mimetypes
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path


def _auth_header(user: str, app_password: str) -> str:
    token = base64.b64encode(f"{user}:{app_password}".encode()).decode()
    return f"Basic {token}"


def _request(
    method: str,
    url: str,
    user: str,
    password: str,
    *,
    data: bytes | None = None,
    headers: dict[str, str] | None = None,
) -> tuple[int, dict | list]:
    h = {"Accept": "application/json", "User-Agent": "article-studio/1.0"}
    h["Authorization"] = _auth_header(user, password)
    if headers:
        h.update(headers)
    req = urllib.request.Request(url, data=data, headers=h, method=method)
    try:
        with urllib.request.urlopen(req, timeout=90) as resp:
            raw = resp.read().decode()
            return resp.getcode(), json.loads(raw) if raw else {}
    except urllib.error.HTTPError as e:
        raw = e.read().decode(errors="replace")
        try:
            payload = json.loads(raw)
        except json.JSONDecodeError:
            payload = {"message": raw[:500]}
        raise RuntimeError(f"WordPress HTTP {e.code} : {payload.get('message', raw[:200])}") from e


def upload_media(
    base_url: str,
    user: str,
    password: str,
    file_path: Path,
    *,
    alt_text: str = "",
    title: str = "",
) -> dict:
    mime, _ = mimetypes.guess_type(str(file_path))
    mime = mime or "image/png"
    boundary = "----ArticleStudioBoundary7MA4YWxk"
    filename = file_path.name
    file_bytes = file_path.read_bytes()

    body = (
        f"--{boundary}\r\n"
        f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n'
        f"Content-Type: {mime}\r\n\r\n"
    ).encode("utf-8") + file_bytes + f"\r\n--{boundary}--\r\n".encode("utf-8")

    url = f"{base_url.rstrip('/')}/wp-json/wp/v2/media"
    _, media = _request(
        "POST",
        url,
        user,
        password,
        data=body,
        headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
    )
    media_id = media.get("id")
    if media_id and (alt_text or title):
        patch: dict = {}
        if alt_text:
            patch["alt_text"] = alt_text
        if title:
            patch["title"] = title
        patch_url = f"{base_url.rstrip('/')}/wp-json/wp/v2/media/{media_id}"
        _request(
            "POST",
            patch_url,
            user,
            password,
            data=json.dumps(patch).encode("utf-8"),
            headers={"Content-Type": "application/json"},
        )
    return media


def create_post(
    base_url: str,
    user: str,
    password: str,
    *,
    title: str,
    content: str,
    excerpt: str = "",
    status: str = "draft",
    slug: str | None = None,
    featured_media_id: int | None = None,
    yoast_title: str | None = None,
    yoast_description: str | None = None,
    yoast_focus: str | None = None,
) -> dict:
    payload: dict = {
        "title": title,
        "content": content,
        "excerpt": excerpt,
        "status": status,
    }
    if slug:
        payload["slug"] = slug
    if featured_media_id:
        payload["featured_media"] = featured_media_id
    meta: dict[str, str] = {}
    if yoast_title:
        meta["_yoast_wpseo_title"] = yoast_title
    if yoast_description:
        meta["_yoast_wpseo_metadesc"] = yoast_description
    if yoast_focus:
        meta["_yoast_wpseo_focuskw"] = yoast_focus
    if meta:
        payload["meta"] = meta

    url = f"{base_url.rstrip('/')}/wp-json/wp/v2/posts"
    _, post = _request(
        "POST",
        url,
        user,
        password,
        data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
    )
    return post


def test_connection(base_url: str, user: str, password: str) -> dict:
    url = f"{base_url.rstrip('/')}/wp-json/wp/v2/users/me"
    _, data = _request("GET", url, user, password)
    return data
