import datetime
import random
from fastapi import APIRouter, Request, Depends, Query
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session, joinedload
from database import get_db
from models import Article, Category, Tag, Advertisement, SiteSettings
from dependencies import csrf_token
from utils import get_setting
from config import settings as app_settings

router = APIRouter()


def _base_ctx(request: Request, db: Session):
    lang = request.query_params.get("lang", request.cookies.get("lang", "en"))
    categories = db.query(Category).filter_by(is_active=True).order_by(Category.order).all()
    breaking = (
        db.query(Article)
        .filter(Article.status == "published", Article.is_breaking == True)
        .order_by(Article.published_at.desc())
        .limit(10)
        .all()
    )
    site_name = get_setting(db, "site_name", "Dabaywa Sudan")
    header_logo = get_setting(db, "header_logo", "/static/images/logo.jpeg")
    footer_logo = get_setting(db, "footer_logo", "/static/images/logo.jpeg")
    return {
        "request": request,
        "lang": lang,
        "categories": categories,
        "breaking_news": breaking,
        "site_name": site_name,
        "header_logo": header_logo,
        "footer_logo": footer_logo,
        "csrf_token": csrf_token(request),
        "vapid_public_key": app_settings.VAPID_PUBLIC_KEY,
        "site_url": app_settings.SITE_URL,
        "now": datetime.datetime.utcnow(),
    }


def _get_ads(db: Session, placement: str, category_id=None, limit=3):
    today = datetime.date.today()
    q = db.query(Advertisement).filter(
        Advertisement.is_active == True,
        Advertisement.placement == placement,
    )
    q = q.filter(
        (Advertisement.start_date == None) | (Advertisement.start_date <= today)
    ).filter(
        (Advertisement.end_date == None) | (Advertisement.end_date >= today)
    )
    if category_id:
        q = q.filter(
            (Advertisement.category_id == None) | (Advertisement.category_id == category_id)
        )
    ads = q.all()
    if len(ads) > limit:
        ads = random.sample(ads, limit)
    return ads


from fastapi.templating import Jinja2Templates
import os

templates = Jinja2Templates(directory=os.path.join(os.path.dirname(__file__), "..", "templates"))


@router.get("/", response_class=HTMLResponse)
async def index(request: Request, db: Session = Depends(get_db)):
    ctx = _base_ctx(request, db)
    pub = Article.status == "published"
    featured = (
        db.query(Article).filter(pub, Article.is_featured == True)
        .order_by(Article.published_at.desc()).limit(5).all()
    )
    latest = (
        db.query(Article).filter(pub)
        .order_by(Article.published_at.desc()).limit(20).all()
    )
    most_read = (
        db.query(Article).filter(pub)
        .order_by(Article.views.desc()).limit(10).all()
    )
    # Per-category sections
    cat_articles = {}
    for cat in ctx["categories"]:
        arts = (
            db.query(Article).filter(pub, Article.category_id == cat.id)
            .order_by(Article.published_at.desc()).limit(4).all()
        )
        if arts:
            cat_articles[cat.id] = arts

    ctx.update({
        "featured_articles": featured,
        "latest_articles": latest,
        "most_read": most_read,
        "cat_articles": cat_articles,
        "header_ads": _get_ads(db, "header", limit=1),
        "sidebar_ads": _get_ads(db, "sidebar", limit=3),
        "between_ads": _get_ads(db, "between_sections", limit=2),
    })
    return templates.TemplateResponse("index.html", ctx)


@router.get("/article/{slug}", response_class=HTMLResponse)
async def article_detail(slug: str, request: Request, db: Session = Depends(get_db)):
    article = (
        db.query(Article).options(joinedload(Article.tags))
        .filter(Article.slug == slug, Article.status == "published").first()
    )
    if not article:
        ctx = _base_ctx(request, db)
        return templates.TemplateResponse("errors/404.html", ctx, status_code=404)
    article.views += 1
    db.commit()
    related = (
        db.query(Article)
        .filter(Article.status == "published", Article.category_id == article.category_id, Article.id != article.id)
        .order_by(Article.published_at.desc()).limit(4).all()
    )
    most_read = (
        db.query(Article).filter(Article.status == "published")
        .order_by(Article.views.desc()).limit(5).all()
    )
    ctx = _base_ctx(request, db)
    ctx.update({
        "article": article,
        "related": related,
        "most_read": most_read,
        "sidebar_ads": _get_ads(db, "sidebar", category_id=article.category_id, limit=2),
        "in_article_ads": _get_ads(db, "in_article", category_id=article.category_id, limit=2),
        "meta_title": article.title_ar if ctx["lang"] == "ar" else article.title_en,
        "meta_desc": (article.meta_description_ar or article.subtitle_ar) if ctx["lang"] == "ar" else (article.meta_description_en or article.subtitle_en),
        "og_image": article.og_image or article.featured_image,
    })
    return templates.TemplateResponse("article.html", ctx)


@router.get("/category/{slug}", response_class=HTMLResponse)
async def category_view(
    slug: str, request: Request, db: Session = Depends(get_db),
    page: int = Query(1, ge=1),
):
    cat = db.query(Category).filter_by(slug=slug, is_active=True).first()
    if not cat:
        ctx = _base_ctx(request, db)
        return templates.TemplateResponse("errors/404.html", ctx, status_code=404)
    per_page = app_settings.ARTICLES_PER_PAGE
    q = (
        db.query(Article)
        .filter(Article.status == "published", Article.category_id == cat.id)
        .order_by(Article.published_at.desc())
    )
    total = q.count()
    articles = q.offset((page - 1) * per_page).limit(per_page).all()
    most_read = (
        db.query(Article).filter(Article.status == "published")
        .order_by(Article.views.desc()).limit(5).all()
    )
    ctx = _base_ctx(request, db)
    ctx.update({
        "category": cat,
        "articles": articles,
        "most_read": most_read,
        "page": page,
        "total_pages": (total + per_page - 1) // per_page,
        "sidebar_ads": _get_ads(db, "sidebar", category_id=cat.id, limit=3),
    })
    return templates.TemplateResponse("category.html", ctx)


@router.get("/tag/{slug}", response_class=HTMLResponse)
async def tag_view(
    slug: str, request: Request, db: Session = Depends(get_db),
    page: int = Query(1, ge=1),
):
    tag = db.query(Tag).filter_by(slug=slug).first()
    if not tag:
        ctx = _base_ctx(request, db)
        return templates.TemplateResponse("errors/404.html", ctx, status_code=404)
    per_page = app_settings.ARTICLES_PER_PAGE
    q = (
        db.query(Article)
        .filter(Article.status == "published", Article.tags.any(Tag.id == tag.id))
        .order_by(Article.published_at.desc())
    )
    total = q.count()
    articles = q.offset((page - 1) * per_page).limit(per_page).all()
    ctx = _base_ctx(request, db)
    ctx.update({
        "tag": tag, "articles": articles,
        "page": page, "total_pages": (total + per_page - 1) // per_page,
    })
    return templates.TemplateResponse("tag.html", ctx)


@router.get("/search", response_class=HTMLResponse)
async def search(
    request: Request, db: Session = Depends(get_db),
    q: str = Query(""), page: int = Query(1, ge=1),
):
    ctx = _base_ctx(request, db)
    per_page = app_settings.ARTICLES_PER_PAGE
    articles = []
    total = 0
    if q.strip():
        like = f"%{q.strip()}%"
        query = (
            db.query(Article)
            .filter(
                Article.status == "published",
                (Article.title_en.ilike(like))
                | (Article.title_ar.ilike(like))
                | (Article.content_en.ilike(like))
                | (Article.content_ar.ilike(like)),
            )
            .order_by(Article.published_at.desc())
        )
        total = query.count()
        articles = query.offset((page - 1) * per_page).limit(per_page).all()
    ctx.update({
        "query": q, "articles": articles,
        "page": page, "total_pages": (total + per_page - 1) // per_page,
    })
    return templates.TemplateResponse("search.html", ctx)


@router.get("/about", response_class=HTMLResponse)
async def about(request: Request, db: Session = Depends(get_db)):
    ctx = _base_ctx(request, db)
    return templates.TemplateResponse("about.html", ctx)


@router.get("/contact", response_class=HTMLResponse)
async def contact(request: Request, db: Session = Depends(get_db)):
    ctx = _base_ctx(request, db)
    return templates.TemplateResponse("contact.html", ctx)


@router.get("/sitemap.xml")
async def sitemap(request: Request, db: Session = Depends(get_db)):
    from fastapi.responses import Response
    articles = db.query(Article).filter_by(status="published").order_by(Article.published_at.desc()).all()
    categories = db.query(Category).filter_by(is_active=True).all()
    base = app_settings.SITE_URL
    xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
    xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
    xml += f"  <url><loc>{base}/</loc><changefreq>hourly</changefreq><priority>1.0</priority></url>\n"
    for cat in categories:
        xml += f"  <url><loc>{base}/category/{cat.slug}</loc><changefreq>daily</changefreq></url>\n"
    for a in articles:
        d = a.published_at.strftime("%Y-%m-%d") if a.published_at else ""
        xml += f"  <url><loc>{base}/article/{a.slug}</loc><lastmod>{d}</lastmod></url>\n"
    xml += "</urlset>"
    return Response(content=xml, media_type="application/xml")


@router.get("/robots.txt")
async def robots():
    from fastapi.responses import PlainTextResponse
    content = f"User-agent: *\nAllow: /\nSitemap: {app_settings.SITE_URL}/sitemap.xml\n"
    return PlainTextResponse(content)
