from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from sqlalchemy import func, desc
from typing import List, Optional
from datetime import datetime, timedelta, date
import logging

from ..database import get_db
from ..models import ContentMetrics, Topic, ContentCalendar
from ..schemas import (
    ContentMetricsCreate, ContentMetricsUpdate, ContentMetricsResponse,
    MetricsDashboard
)
from .auth import get_current_user

router = APIRouter(prefix="/api/metrics", tags=["metrics"])


@router.get("/dashboard", response_model=MetricsDashboard)
def get_dashboard(
    days: int = Query(30, ge=1, le=365),
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    since = datetime.now() - timedelta(days=days)

    total_topics = db.query(Topic).count()

    raw_status = db.query(Topic.status, func.count()).group_by(Topic.status).all()
    topics_by_status = {}
    for s, cnt in raw_status:
        topics_by_status[s] = cnt

    total_published = db.query(ContentMetrics).filter(
        ContentMetrics.views > 0
    ).count()

    all_metrics = db.query(ContentMetrics).filter(
        ContentMetrics.created_at >= since
    ).all()

    total_views = sum(m.views for m in all_metrics)
    total_likes = sum(m.likes for m in all_metrics)

    engagement_rates = [m.engagement_rate for m in all_metrics if m.views > 0]
    avg_engagement = sum(engagement_rates) / len(engagement_rates) if engagement_rates else 0

    top_topics_data = db.query(
        ContentMetrics.topic_id,
        func.sum(ContentMetrics.views).label("total_views"),
        func.sum(ContentMetrics.likes).label("total_likes")
    ).join(Topic).filter(
        ContentMetrics.created_at >= since
    ).group_by(ContentMetrics.topic_id).order_by(desc("total_views")).limit(10).all()

    top_topics = []
    for row in top_topics_data:
        topic = db.query(Topic).filter(Topic.id == row.topic_id).first()
        top_topics.append({
            "topic_id": row.topic_id,
            "title": topic.title if topic else row.topic_id,
            "total_views": row.total_views or 0,
            "total_likes": row.total_likes or 0,
        })

    recent_metrics = db.query(ContentMetrics).order_by(
        ContentMetrics.created_at.desc()
    ).limit(10).all()

    return MetricsDashboard(
        total_topics=total_topics,
        topics_by_status=topics_by_status,
        total_published=total_published,
        total_views=total_views,
        total_likes=total_likes,
        avg_engagement_rate=round(avg_engagement, 2),
        top_topics=top_topics,
        recent_metrics=[ContentMetricsResponse.model_validate(m) for m in recent_metrics]
    )


@router.get("/trend")
def get_trend(
    days: int = Query(30, ge=1, le=365),
    group_by: str = Query("day", enum=["day", "week", "month"]),
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    since = datetime.now() - timedelta(days=days)

    if group_by == "day":
        date_format = func.date(ContentMetrics.created_at)
    else:
        date_format = func.date_trunc(group_by, ContentMetrics.created_at)

    rows = db.query(
        date_format.label("period"),
        func.sum(ContentMetrics.views).label("views"),
        func.sum(ContentMetrics.likes).label("likes"),
        func.sum(ContentMetrics.comments).label("comments"),
        func.count(ContentMetrics.id).label("count")
    ).filter(
        ContentMetrics.created_at >= since
    ).group_by(date_format).order_by(date_format).all()

    return [
        {
            "period": str(row.period),
            "views": row.views or 0,
            "likes": row.likes or 0,
            "comments": row.comments or 0,
            "count": row.count or 0
        }
        for row in rows
    ]


@router.get("/entries", response_model=List[ContentMetricsResponse])
def list_metrics(
    topic_id: Optional[str] = None,
    platform: Optional[str] = None,
    limit: int = Query(50, le=200),
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    query = db.query(ContentMetrics)
    if topic_id:
        query = query.filter(ContentMetrics.topic_id == topic_id)
    if platform:
        query = query.filter(ContentMetrics.platform == platform)
    return query.order_by(ContentMetrics.created_at.desc()).limit(limit).all()


@router.post("/entries", response_model=ContentMetricsResponse)
def create_metric(
    data: ContentMetricsCreate,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    topic = db.query(Topic).filter(Topic.id == data.topic_id).first()
    if not topic:
        raise HTTPException(status_code=404, detail="选题不存在")

    existing = db.query(ContentMetrics).filter(
        ContentMetrics.topic_id == data.topic_id,
        ContentMetrics.platform == data.platform
    ).first()

    if existing:
        for k, v in data.model_dump(exclude_unset=True).items():
            if k != "topic_id" and k != "platform":
                setattr(existing, k, v)
        existing.last_fetched = datetime.now()
        db.commit()
        db.refresh(existing)
        return existing

    metric = ContentMetrics(**data.model_dump(), last_fetched=datetime.now())
    db.add(metric)
    db.commit()
    db.refresh(metric)
    return metric


@router.put("/entries/{metric_id}", response_model=ContentMetricsResponse)
def update_metric(
    metric_id: int,
    data: ContentMetricsUpdate,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    metric = db.query(ContentMetrics).filter(ContentMetrics.id == metric_id).first()
    if not metric:
        raise HTTPException(status_code=404, detail="数据记录不存在")

    for k, v in data.model_dump(exclude_unset=True).items():
        setattr(metric, k, v)
    metric.last_fetched = datetime.now()
    db.commit()
    db.refresh(metric)
    return metric


@router.delete("/entries/{metric_id}")
def delete_metric(
    metric_id: int,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    metric = db.query(ContentMetrics).filter(ContentMetrics.id == metric_id).first()
    if not metric:
        raise HTTPException(status_code=404, detail="数据记录不存在")
    db.delete(metric)
    db.commit()
    return {"ok": True}


@router.get("/topics/{topic_id}", response_model=List[ContentMetricsResponse])
def get_topic_metrics(
    topic_id: str,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    topic = db.query(Topic).filter(Topic.id == topic_id).first()
    if not topic:
        raise HTTPException(status_code=404, detail="选题不存在")
    return db.query(ContentMetrics).filter(
        ContentMetrics.topic_id == topic_id
    ).order_by(ContentMetrics.created_at.desc()).all()


@router.get("/by-platform")
def get_metrics_by_platform(
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    rows = db.query(
        ContentMetrics.platform,
        func.sum(ContentMetrics.views).label("total_views"),
        func.sum(ContentMetrics.likes).label("total_likes"),
        func.sum(ContentMetrics.comments).label("total_comments"),
        func.count(ContentMetrics.id).label("count")
    ).group_by(ContentMetrics.platform).all()

    return [
        {
            "platform": row.platform,
            "total_views": row.total_views or 0,
            "total_likes": row.total_likes or 0,
            "total_comments": row.total_comments or 0,
            "count": row.count or 0,
            "avg_views": (row.total_views or 0) / (row.count or 1),
            "avg_likes": (row.total_likes or 0) / (row.count or 1),
        }
        for row in rows
    ]


@router.get("/recommend-topics")
def recommend_topics_from_metrics(
    limit: int = Query(10, le=50),
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user)
):
    try:
        high_performing = db.query(
            ContentMetrics.topic_id,
            func.avg(ContentMetrics.engagement_rate).label("avg_engagement"),
            func.max(ContentMetrics.views).label("max_views")
        ).group_by(ContentMetrics.topic_id).order_by(desc("avg_engagement")).limit(20).all()

        recommendations = []
        for row in high_performing:
            topic = db.query(Topic).filter(Topic.id == row.topic_id).first()
            if not topic:
                continue
            metrics = db.query(ContentMetrics).filter(
                ContentMetrics.topic_id == row.topic_id
            ).all()
            recommendations.append({
                "topic_id": row.topic_id,
                "title": topic.title,
                "field": topic.field_name,
                "status": topic.status,
                "avg_engagement": round(float(row.avg_engagement), 2) if row.avg_engagement else 0,
                "max_views": int(row.max_views) if row.max_views else 0,
                "platforms": list(set(m.platform for m in metrics)),
                "reason": f"平均互动率 {round(float(row.avg_engagement), 2) if row.avg_engagement else 0}%，最高阅读 {int(row.max_views) if row.max_views else 0}"
            })

        return recommendations[:limit]
    except Exception as e:
        logging.getLogger(__name__).exception(f"推荐选题失败: {e}")
        return []