from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from pydantic import BaseModel
from typing import Optional
from datetime import datetime

from app.api.deps import get_db, get_tenant_by_appid_or_domain as get_tenant_by_domain
from app.core.models.article import Article

router = APIRouter(prefix="/store/articles", tags=["store-articles"])


class ArticlePublicOut(BaseModel):
    id:              int
    title:           str
    slug:            str
    content:         Optional[str] = None
    excerpt:         Optional[str] = None
    featured_image:  Optional[str] = None
    author_name:     Optional[str] = None
    published_at:    Optional[datetime] = None
    view_count:      int = 0
    seo_title:       Optional[str] = None
    seo_description: Optional[str] = None
    seo_keywords:    Optional[str] = None
    og_image:        Optional[str] = None
    canonical_url:   Optional[str] = None
    content_blocks:  Optional[list] = None
    created_at:      Optional[datetime] = None

    model_config = {"from_attributes": True}


class ArticleListItem(BaseModel):
    id:             int
    title:          str
    slug:           str
    excerpt:        Optional[str] = None
    featured_image: Optional[str] = None
    author_name:    Optional[str] = None
    published_at:   Optional[datetime] = None
    view_count:     int = 0
    created_at:     Optional[datetime] = None

    model_config = {"from_attributes": True}


def _apply_locale(article: Article, locale: str) -> dict:
    use_en = locale == 'en'
    d = ArticlePublicOut.model_validate(article).model_dump()
    if use_en:
        if article.title_en:           d['title']           = article.title_en
        if article.content_en:         d['content']         = article.content_en
        if article.excerpt_en:         d['excerpt']         = article.excerpt_en
        if article.seo_title_en:       d['seo_title']       = article.seo_title_en
        if article.seo_description_en: d['seo_description'] = article.seo_description_en
        if article.seo_keywords_en:    d['seo_keywords']    = article.seo_keywords_en
    return d


@router.get("", response_model=dict)
async def list_articles(
    tid:      int = Depends(get_tenant_by_domain),
    page:     int = Query(1, ge=1),
    per_page: int = Query(12, ge=1, le=50),
    locale:   str = Query('zh'),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = tid
    q = select(Article).where(Article.tenant_id == tenant_id, Article.status == "published")
    total = (await db.execute(select(func.count()).select_from(q.subquery()))).scalar()
    rows  = (await db.execute(q.order_by(Article.published_at.desc()).offset((page-1)*per_page).limit(per_page))).scalars().all()
    use_en = locale == 'en'
    items = []
    for a in rows:
        item = ArticleListItem.model_validate(a).model_dump()
        if use_en:
            if a.title_en:   item['title']   = a.title_en
            if a.excerpt_en: item['excerpt'] = a.excerpt_en
        items.append(item)
    return {"total": total, "page": page, "per_page": per_page, "items": items}


@router.get("/preview/{token}", response_model=dict, summary="草稿预览（无需登录）")
async def get_article_preview(
    token: str,
    tid: int = Depends(get_tenant_by_domain),
    db: AsyncSession = Depends(get_db),
):
    obj = (await db.execute(
        select(Article).where(Article.preview_token == token, Article.tenant_id == tid)
    )).scalar_one_or_none()
    if not obj:
        raise HTTPException(404, "Preview not found")
    d = ArticlePublicOut.model_validate(obj).model_dump()
    d["content_blocks"] = obj.content_blocks or []
    return d


@router.get("/{slug}", response_model=dict)
async def get_article_by_slug(
    slug:   str,
    tid:    int = Depends(get_tenant_by_domain),
    locale: str = Query('zh'),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = tid
    obj = (await db.execute(
        select(Article).where(Article.tenant_id == tenant_id, Article.slug == slug, Article.status == "published")
    )).scalar_one_or_none()
    if not obj:
        raise HTTPException(404, "Article not found")
    obj.view_count = (obj.view_count or 0) + 1
    await db.commit()
    await db.refresh(obj)
    return _apply_locale(obj, locale)
