"""
Sitemap and feed views for shops.

Provides XML sitemap and RSS/Atom feeds for public products and content.
Only includes public items (visibility=1), excludes unlisted, private,
coupons, carts, and user profile pages.
"""
from datetime import datetime
from xml.etree.ElementTree import Element, SubElement, tostring

from pyramid.response import Response
from pyramid.view import view_config

from ..models.product import Product


def timestamp_to_sitemap_date(timestamp):
    """Convert millisecond timestamp to YYYY-MM-DD format for sitemaps."""
    if timestamp:
        dt = datetime.utcfromtimestamp(timestamp / 1000.0)
        return dt.strftime("%Y-%m-%d")
    return datetime.utcnow().strftime("%Y-%m-%d")


def timestamp_to_atom_datetime(timestamp):
    """Convert millisecond timestamp to ISO 8601 format for Atom feeds."""
    if timestamp:
        dt = datetime.utcfromtimestamp(timestamp / 1000.0)
        return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
    return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")


def timestamp_to_rfc822(timestamp):
    """Convert millisecond timestamp to RFC 822 format for RSS."""
    if timestamp:
        dt = datetime.fromtimestamp(timestamp / 1000.0)
        return dt.strftime("%a, %d %b %Y %H:%M:%S +0000")
    return datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000")


def get_public_items(shop):
    """Get all public products and content from a shop."""
    if not shop:
        return [], []

    products = (
        shop.products.filter(Product.visibility == 1, Product.is_sellable == True)
        .order_by(Product.updated_timestamp.desc())
        .limit(1000)
        .all()
    )

    content = (
        shop.products.filter(Product.visibility == 1, Product.is_sellable == False)
        .order_by(Product.updated_timestamp.desc())
        .limit(1000)
        .all()
    )

    return products, content


def build_sitemap_xml(request, shop, products, content):
    """Build XML sitemap for the shop."""
    urlset = Element("urlset")
    urlset.set("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9")

    # Shop home page
    url = SubElement(urlset, "url")
    SubElement(url, "loc").text = shop.absolute_url(request)
    SubElement(url, "lastmod").text = timestamp_to_sitemap_date(shop.updated_timestamp)
    SubElement(url, "changefreq").text = "weekly"
    SubElement(url, "priority").text = "1.0"

    # Shop about page
    url = SubElement(urlset, "url")
    SubElement(url, "loc").text = shop.absolute_about_url(request)
    SubElement(url, "lastmod").text = timestamp_to_sitemap_date(shop.updated_timestamp)
    SubElement(url, "changefreq").text = "monthly"
    SubElement(url, "priority").text = "0.5"

    # Terms of service (if exists)
    if shop.terms_of_service_raw:
        url = SubElement(urlset, "url")
        SubElement(url, "loc").text = shop.absolute_terms_url(request)
        SubElement(url, "lastmod").text = timestamp_to_sitemap_date(shop.updated_timestamp)
        SubElement(url, "changefreq").text = "yearly"
        SubElement(url, "priority").text = "0.3"

    # Privacy policy (if exists)
    if shop.privacy_policy_raw:
        url = SubElement(urlset, "url")
        SubElement(url, "loc").text = shop.absolute_privacy_policy_url(request)
        SubElement(url, "lastmod").text = timestamp_to_sitemap_date(shop.updated_timestamp)
        SubElement(url, "changefreq").text = "yearly"
        SubElement(url, "priority").text = "0.3"

    # Public products
    for product in products:
        url = SubElement(urlset, "url")
        SubElement(url, "loc").text = product.absolute_url(request)
        SubElement(url, "lastmod").text = timestamp_to_sitemap_date(product.updated_timestamp)
        SubElement(url, "changefreq").text = "weekly"
        SubElement(url, "priority").text = "0.8"

    # Public content
    for item in content:
        url = SubElement(urlset, "url")
        SubElement(url, "loc").text = item.absolute_url(request)
        SubElement(url, "lastmod").text = timestamp_to_sitemap_date(item.updated_timestamp)
        SubElement(url, "changefreq").text = "weekly"
        SubElement(url, "priority").text = "0.7"

    return tostring(urlset, encoding="unicode", method="xml")


def build_rss_xml(request, shop, products, content):
    """Build RSS 2.0 feed for the shop."""
    rss = Element("rss")
    rss.set("version", "2.0")
    rss.set("xmlns:atom", "http://www.w3.org/2005/Atom")

    channel = SubElement(rss, "channel")
    SubElement(channel, "title").text = shop.name
    SubElement(channel, "link").text = shop.absolute_url(request)
    SubElement(channel, "description").text = shop.description or f"Products and content from {shop.name}"
    SubElement(channel, "language").text = "en-us"
    SubElement(channel, "lastBuildDate").text = timestamp_to_rfc822(shop.updated_timestamp)

    # Atom self-link for feed validation
    atom_link = SubElement(channel, "atom:link")
    atom_link.set("href", f"{request.host_url}/rss.xml")
    atom_link.set("rel", "self")
    atom_link.set("type", "application/rss+xml")

    # Combine and sort by updated timestamp
    all_items = [(p, p.updated_timestamp) for p in products] + [
        (c, c.updated_timestamp) for c in content
    ]
    all_items.sort(key=lambda x: x[1], reverse=True)

    for item_obj, _ in all_items:
        item = SubElement(channel, "item")
        SubElement(item, "title").text = item_obj.title
        SubElement(item, "link").text = item_obj.absolute_url(request)
        SubElement(item, "guid").text = item_obj.absolute_url(request)
        SubElement(item, "pubDate").text = timestamp_to_rfc822(item_obj.created_timestamp)

        # Use description_html stripped of tags, or fall back to raw
        if item_obj.description:
            SubElement(item, "description").text = item_obj.description[:500]

    return tostring(rss, encoding="unicode", method="xml")


def build_atom_xml(request, shop, products, content):
    """Build Atom feed for the shop."""
    feed = Element("feed")
    feed.set("xmlns", "http://www.w3.org/2005/Atom")

    SubElement(feed, "title").text = shop.name
    SubElement(feed, "id").text = shop.absolute_url(request)
    SubElement(feed, "updated").text = timestamp_to_atom_datetime(shop.updated_timestamp)

    # Self link
    self_link = SubElement(feed, "link")
    self_link.set("href", f"{request.host_url}/atom.xml")
    self_link.set("rel", "self")
    self_link.set("type", "application/atom+xml")

    # Alternate link
    alt_link = SubElement(feed, "link")
    alt_link.set("href", shop.absolute_url(request))
    alt_link.set("rel", "alternate")
    alt_link.set("type", "text/html")

    if shop.description:
        SubElement(feed, "subtitle").text = shop.description

    # Combine and sort by updated timestamp
    all_items = [(p, p.updated_timestamp) for p in products] + [
        (c, c.updated_timestamp) for c in content
    ]
    all_items.sort(key=lambda x: x[1], reverse=True)

    for item_obj, _ in all_items:
        entry = SubElement(feed, "entry")
        SubElement(entry, "title").text = item_obj.title
        SubElement(entry, "id").text = item_obj.absolute_url(request)
        SubElement(entry, "updated").text = timestamp_to_atom_datetime(item_obj.updated_timestamp)
        SubElement(entry, "published").text = timestamp_to_atom_datetime(item_obj.created_timestamp)

        link = SubElement(entry, "link")
        link.set("href", item_obj.absolute_url(request))
        link.set("rel", "alternate")
        link.set("type", "text/html")

        if item_obj.description:
            summary = SubElement(entry, "summary")
            summary.set("type", "text")
            summary.text = item_obj.description[:500]

    return tostring(feed, encoding="unicode", method="xml")


@view_config(route_name="sitemap")
def sitemap_view(request):
    """Generate XML sitemap for the shop."""
    shop = request.shop

    if not shop or shop.is_non_production:
        response = Response(body="<?xml version='1.0' encoding='UTF-8'?><urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'></urlset>")
        response.content_type = "application/xml"
        return response

    products, content = get_public_items(shop)
    xml = build_sitemap_xml(request, shop, products, content)

    response = Response(body=f"<?xml version='1.0' encoding='UTF-8'?>\n{xml}")
    response.content_type = "application/xml"
    return response


@view_config(route_name="rss")
@view_config(route_name="feed_xml")
@view_config(route_name="feed_rss")
def rss_view(request):
    """Generate RSS 2.0 feed for the shop."""
    shop = request.shop

    if not shop or shop.is_non_production:
        response = Response(body="<?xml version='1.0' encoding='UTF-8'?><rss version='2.0'><channel></channel></rss>")
        response.content_type = "application/xml"
        return response

    products, content = get_public_items(shop)
    xml = build_rss_xml(request, shop, products, content)

    response = Response(body=f"<?xml version='1.0' encoding='UTF-8'?>\n{xml}")
    response.content_type = "application/xml"
    return response


@view_config(route_name="atom")
@view_config(route_name="feed_atom")
def atom_view(request):
    """Generate Atom feed for the shop."""
    shop = request.shop

    if not shop or shop.is_non_production:
        response = Response(body="<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'></feed>")
        response.content_type = "application/xml"
        return response

    products, content = get_public_items(shop)
    xml = build_atom_xml(request, shop, products, content)

    response = Response(body=f"<?xml version='1.0' encoding='UTF-8'?>\n{xml}")
    response.content_type = "application/xml"
    return response
