import datetime
import json as libjson
import xml.etree.ElementTree as ElementTree
from typedef import *
from util import *


def _format_atom_date(date: datetime.date) -> str:
    return date_to_datetime(date).astimezone(datetime.timezone.utc).isoformat()


def _get_feed_title(site_config: any) -> str:
    return f"{site_config['person']['nickname']}'s blog"


def atom(site_config: any, posts: list[AbbreviatedPost]) -> str:
    root = ElementTree.Element("feed", xmlns="http://www.w3.org/2005/Atom")

    blog_url = get_absolute_url(site_config, "/blog/")
    feed_url = get_absolute_url(site_config, "/blog/feed.atom")

    ElementTree.SubElement(root, "title").text = _get_feed_title(site_config)
    ElementTree.SubElement(root, "id").text = blog_url
    ElementTree.SubElement(root, "updated").text = (
        _format_atom_date(
            max(
                [post.publishedDate for post in posts]
                + [post.updatedDate for post in posts if post.updatedDate is not None]
            )
        )
        if len(posts) != 0
        else ""
    )
    _atom_link(root, blog_url, rel="alternate")
    _atom_link(root, feed_url, rel="self")
    ElementTree.SubElement(
        ElementTree.SubElement(root, "author"),
        "name",
    ).text = f"{site_config['person']['firstName']} {site_config['person']['surname']}"

    for post in posts:
        entry = ElementTree.SubElement(root, "entry")
        ElementTree.SubElement(entry, "title").text = post.title
        ElementTree.SubElement(entry, "updated").text = _format_atom_date(
            post.updatedDate if post.updatedDate is not None else post.publishedDate
        )
        ElementTree.SubElement(entry, "id").text = post.slug
        _atom_link(entry, get_absolute_url(site_config, f"/blog/{post.slug}/"))
        ElementTree.SubElement(entry, "summary", type="text").text = post.description

    ElementTree.indent(root)  # pretty formatting

    return ElementTree.tostring(root, xml_declaration=True, encoding="unicode")


def _atom_link(entry: ElementTree.Element, href: str, rel: str | None = None):
    kwargs = {"href": href}
    if rel is not None:
        kwargs["rel"] = rel
    ElementTree.SubElement(entry, "link", **kwargs)


def json(site_config: any, posts: list[AbbreviatedPost]) -> str:
    root = {
        "version": "https://jsonfeed.org/version/1.1",
        "title": _get_feed_title(site_config),
        "home_page_url": get_absolute_url(site_config, "/blog/"),
        "feed_url": get_absolute_url(site_config, "/blog/feed.json"),
        "authors": [
            {
                "name": f"{site_config['person']['firstName']} {site_config['person']['surname']}"
            }
        ],
        "items": [],
    }

    for post in posts:
        x = {
            "id": post.slug,
            "url": get_absolute_url(site_config, f"/blog/{post.slug}/"),
            "title": post.title,
            "content_text": "",
            "date_published": _format_atom_date(post.publishedDate),
        }
        if post.description != "":
            x["summary"] = post.description
        if post.updatedDate is not None:
            x["date_modified"] = _format_atom_date(post.updatedDate)
        root["items"].append(x)

    return libjson.dumps(root, indent="\t")
