"""
SEO 公开 API
- GET /api/sitemap.xml          → 站点 sitemap（按租户隔离）
- GET /api/robots.txt           → robots.txt
- GET /api/store/seo/product/{slug} → 商品 SEO 数据 + JSON-LD
"""
import logging
from datetime import datetime
from decimal import Decimal
from typing import Optional

from fastapi import APIRouter, Depends, Query, Request
from fastapi.responses import PlainTextResponse, Response
from sqlalchemy import select, func, text
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import noload

from app.api.deps import get_db
from app.core.models.product import Product
from app.core.models.brand import Brand
from app.core.models.category import Category
from app.core.services.tenant import resolve_public_tenant_id
from app.common.seo import generate_product_jsonld, generate_product_seo_tags

logger = logging.getLogger(__name__)

router = APIRouter(tags=["SEO"])


# ── helpers ───────────────────────────────────────────────────────────────────

def _tenant_id_from_request(request: Request, db: AsyncSession, tid: Optional[int]) -> int:
    """从请求中解析 tenant_id（优先查 subdomain / header / query）"""
    # 先用已解析的 tid（来自 Depends）
    if tid:
        return tid
    # 从 X-Tenant-ID header 取
    header_tid = request.headers.get("X-Tenant-ID")
    if header_tid:
        try:
            return int(header_tid)
        except (ValueError, TypeError):
            pass
    return tid or 1


def _build_product_variants_dict(product: Product, brand_name: str, tenant_slug: str, base_url: str) -> list[dict]:
    """从 ORM 对象提取 variants 列表（用于 JSON-LD）"""
    variants = []
    for v in (product.variants or []):
        variants.append({
            "sku": v.sku,
            "price": float(v.price_modifier or Decimal("0")),
            "url": f"{base_url.rstrip('/')}/{tenant_slug}/products/{product.slug}",
            "image": v.image_url or "",
        })
    return variants


# ── GET /api/store/seo/product/{slug} ────────────────────────────────────────

@router.get("/store/seo/product/{slug}", summary="商品 SEO 数据")
async def get_product_seo(
    slug: str,
    request: Request,
    db: AsyncSession = Depends(get_db),
    tid: int = Query(None),
):
    """
    返回商品 SEO 数据：meta_title, meta_description, json_ld, og_image
    结合 Brand.name 生成 JSON-LD
    """
    tenant_id = await resolve_public_tenant_id(db, tenant_id=tid, request=request)

    # 读取商品 + brand + category
    result = await db.execute(
        select(Product).where(
            Product.tenant_id == tenant_id,
            Product.slug == slug,
            Product.status == "active",
        ).options(
            noload(Product.variants),
            noload(Product.images),
        )
    )
    product = result.scalar_one_or_none()
    if not product:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")

    brand_name = ""
    if product.brand_id:
        brand_res = await db.execute(select(Brand.name).where(Brand.id == product.brand_id))
        brand_row = brand_res.scalar_one_or_none()
        if brand_row:
            brand_name = brand_row

    category_name = ""
    if product.category_id:
        cat_res = await db.execute(select(Category.name).where(Category.id == product.category_id))
        cat_row = cat_res.scalar_one_or_none()
        if cat_row:
            category_name = cat_row

    tenant_slug = f"tenant-{tenant_id}"  # 假设 slug 规则，实际可查 tenants 表
    base_url = request.base_url or "https://example.com"

    # 生成 JSON-LD
    variants = _build_product_variants_dict(product, brand_name, tenant_slug, str(base_url))
    json_ld = generate_product_jsonld(
        product=product,
        brand=brand_name,
        variants=variants,
        tenant_slug=tenant_slug,
        base_url=str(base_url),
    )

    # 生成 SEO tags
    seo_tags = generate_product_seo_tags(
        product_name=product.name,
        category_name=category_name,
        brand_name=brand_name,
        meta_title=product.meta_title,
        meta_description=product.meta_description,
    )

    return {
        "slug": product.slug,
        "name": product.name,
        "meta_title": seo_tags["title"],
        "meta_description": seo_tags["description"],
        "og_image": product.og_image or product.cover_url or "",
        "json_ld": json_ld,
    }


# ── GET /api/robots.txt ───────────────────────────────────────────────────────

@router.get("/robots.txt", response_class=PlainTextResponse, summary="robots.txt")
async def get_robots_txt(
    request: Request,
    db: AsyncSession = Depends(get_db),
    tid: int = Query(None),
):
    """
    返回 robots.txt，禁止爬虫访问敏感路径
    """
    tenant_id = _tenant_id_from_request(request, db, tid)
    base_url = str(request.base_url).rstrip("/")

    content = f"""User-agent: *
Allow: /
Disallow: /account/*
Disallow: /cart/*
Disallow: /checkout/*
Disallow: /auth/*
Disallow: /api/account/*
Disallow: /api/cart/*
Disallow: /api/checkout/*
Disallow: /api/auth/*

# Sitemap
Sitemap: {base_url}/api/sitemap.xml?tid={tenant_id}
"""
    return PlainTextResponse(content=content)


# ── GET /api/sitemap.xml ─────────────────────────────────────────────────────

@router.get("/sitemap.xml", summary="站点 sitemap（XML）")
async def get_sitemap_xml(
    request: Request,
    db: AsyncSession = Depends(get_db),
    tid: int = Query(None),
):
    """
    返回 sitemap.xml，按租户隔离，只包含 active 商品/分类/品牌
    异步生成，避免大文件阻塞
    """
    tenant_id = _tenant_id_from_request(request, db, tid)
    base_url = str(request.base_url).rstrip("/")

    # 并行查询 active 商品、分类、品牌
    products_res = await db.execute(
        select(Product.slug, Product.updated_at).where(
            Product.tenant_id == tenant_id,
            Product.status == "active",
        ).order_by(Product.updated_at.desc()).limit(50000)
    )
    products = products_res.all()

    categories_res = await db.execute(
        select(Category.slug, Category.updated_at).where(
            Category.tenant_id == tenant_id,
            Category.is_active == 1,
        ).order_by(Category.updated_at.desc()).limit(2000)
    )
    categories = categories_res.all()

    brands_res = await db.execute(
        select(Brand.slug, Brand.updated_at).where(
            Brand.tenant_id == tenant_id,
            Brand.is_active == 1,
        ).order_by(Brand.updated_at.desc()).limit(1000)
    )
    brands = brands_res.all()

    tenant_slug = f"tenant-{tenant_id}"

    def url_entry(loc: str, lastmod: Optional[datetime], priority: str, changefreq: str) -> str:
        lastmod_xml = f"<lastmod>{lastmod.strftime('%Y-%m-%d')}</lastmod>" if lastmod else ""
        return (
            f"<url>\n"
            f"  <loc>{loc}</loc>\n"
            f"  {lastmod_xml}"
            f"  <changefreq>{changefreq}</changefreq>\n"
            f"  <priority>{priority}</priority>\n"
            f"</url>"
        )

    url_lines: list[str] = ['<?xml version="1.0" encoding="UTF-8"?>',
                              '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">']

    # 主页
    url_lines.append(url_entry(f"{base_url}/{tenant_slug}/", None, "1.0", "daily"))

    # 商品页
    for (slug, updated_at) in products:
        url_lines.append(url_entry(
            f"{base_url}/{tenant_slug}/products/{slug}",
            updated_at,
            "0.8",
            "weekly",
        ))

    # 分类页
    for (slug, updated_at) in categories:
        url_lines.append(url_entry(
            f"{base_url}/{tenant_slug}/category/{slug}",
            updated_at,
            "0.6",
            "weekly",
        ))

    # 品牌页
    for (slug, updated_at) in brands:
        url_lines.append(url_entry(
            f"{base_url}/{tenant_slug}/brands/{slug}",
            updated_at,
            "0.5",
            "monthly",
        ))

    url_lines.append("</urlset>")

    xml_content = "\n".join(url_lines)
    return Response(
        content=xml_content,
        media_type="application/xml; charset=utf-8",
    )
