"""效果追踪服务"""
import logging
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func

from app.models.analytics import PublishRecord, ContentMetrics

logger = logging.getLogger(__name__)


class AnalyticsTracker:
    def __init__(self, session: AsyncSession):
        self.session = session

    async def record_publish(self, organization_id: str, data: dict) -> PublishRecord:
        """记录发布事件"""
        record = PublishRecord(
            organization_id=organization_id,
            content_title=data["content_title"],
            content_id=data.get("content_id"),
            platform=data["platform"],
            published_url=data.get("published_url"),
            status=data.get("status", "published"),
            published_at=data.get("published_at") or datetime.utcnow(),
        )
        self.session.add(record)
        await self.session.commit()
        await self.session.refresh(record)
        logger.info("记录发布事件 id=%s platform=%s", record.id, record.platform)
        return record

    async def update_metrics(self, publish_record_id: str, metrics: dict) -> ContentMetrics:
        """更新/添加效果指标（追加一条快照记录）"""
        entry = ContentMetrics(
            publish_record_id=publish_record_id,
            views=metrics.get("views", 0),
            likes=metrics.get("likes", 0),
            comments=metrics.get("comments", 0),
            shares=metrics.get("shares", 0),
            bookmarks=metrics.get("bookmarks", 0),
            ai_citation_count=metrics.get("ai_citation_count", 0),
            search_impressions=metrics.get("search_impressions", 0),
            search_clicks=metrics.get("search_clicks", 0),
            avg_read_duration=metrics.get("avg_read_duration", 0.0),
            read_completion_rate=metrics.get("read_completion_rate", 0.0),
        )
        self.session.add(entry)
        await self.session.commit()
        await self.session.refresh(entry)
        return entry

    async def get_overview(self, organization_id: str) -> dict:
        """
        获取全局概览统计
        返回:
            total_published, total_views, total_interactions,
            total_ai_citations, avg_engagement_rate, platform_distribution
        """
        # 取各 publish_record 的最新一条 metrics 做聚合
        # 先找该组织所有发布记录
        pr_stmt = select(PublishRecord.id, PublishRecord.platform).where(
            PublishRecord.organization_id == organization_id
        )
        pr_result = await self.session.execute(pr_stmt)
        records = pr_result.all()

        total_published = len(records)
        platform_distribution: dict[str, int] = {}
        record_ids = []
        for r in records:
            record_ids.append(r.id)
            platform_distribution[r.platform] = platform_distribution.get(r.platform, 0) + 1

        if not record_ids:
            return {
                "total_published": 0,
                "total_views": 0,
                "total_interactions": 0,
                "total_ai_citations": 0,
                "avg_engagement_rate": 0.0,
                "platform_distribution": {},
            }

        # 每条发布记录取最新快照
        subq = (
            select(
                ContentMetrics.publish_record_id,
                func.max(ContentMetrics.recorded_at).label("latest"),
            )
            .where(ContentMetrics.publish_record_id.in_(record_ids))
            .group_by(ContentMetrics.publish_record_id)
            .subquery()
        )
        metrics_stmt = (
            select(ContentMetrics)
            .join(
                subq,
                (ContentMetrics.publish_record_id == subq.c.publish_record_id)
                & (ContentMetrics.recorded_at == subq.c.latest),
            )
        )
        metrics_result = await self.session.execute(metrics_stmt)
        latest_metrics = metrics_result.scalars().all()

        total_views = sum(m.views for m in latest_metrics)
        total_interactions = sum(m.likes + m.comments + m.shares for m in latest_metrics)
        total_ai_citations = sum(m.ai_citation_count for m in latest_metrics)

        # 互动率 = (likes+comments+shares) / views，取平均
        engagement_rates = []
        for m in latest_metrics:
            if m.views > 0:
                engagement_rates.append((m.likes + m.comments + m.shares) / m.views)
        avg_engagement_rate = (
            round(sum(engagement_rates) / len(engagement_rates), 4)
            if engagement_rates
            else 0.0
        )

        return {
            "total_published": total_published,
            "total_views": total_views,
            "total_interactions": total_interactions,
            "total_ai_citations": total_ai_citations,
            "avg_engagement_rate": avg_engagement_rate,
            "platform_distribution": platform_distribution,
        }

    async def get_content_performance(self, publish_record_id: str) -> dict:
        """获取单条内容的详细表现（含历史指标快照列表）"""
        pr_stmt = select(PublishRecord).where(PublishRecord.id == publish_record_id)
        pr_result = await self.session.execute(pr_stmt)
        record = pr_result.scalar_one_or_none()
        if not record:
            return {}

        metrics_stmt = (
            select(ContentMetrics)
            .where(ContentMetrics.publish_record_id == publish_record_id)
            .order_by(ContentMetrics.recorded_at.asc())
        )
        metrics_result = await self.session.execute(metrics_stmt)
        metrics_list = metrics_result.scalars().all()

        latest = metrics_list[-1] if metrics_list else None

        return {
            "id": record.id,
            "content_title": record.content_title,
            "platform": record.platform,
            "published_url": record.published_url,
            "status": record.status,
            "published_at": record.published_at.isoformat() if record.published_at else None,
            "latest_metrics": _metrics_to_dict(latest) if latest else None,
            "metrics_history": [_metrics_to_dict(m) for m in metrics_list],
        }

    async def get_top_performing(
        self, organization_id: str, limit: int = 10, sort_by: str = "views"
    ) -> list[dict]:
        """获取表现最好的内容排行"""
        ALLOWED_SORT = {
            "views", "likes", "comments", "shares",
            "ai_citation_count", "read_completion_rate",
        }
        if sort_by not in ALLOWED_SORT:
            sort_by = "views"

        pr_stmt = select(PublishRecord.id).where(
            PublishRecord.organization_id == organization_id
        )
        pr_result = await self.session.execute(pr_stmt)
        record_ids = [r.id for r in pr_result.all()]

        if not record_ids:
            return []

        # 取每条记录最新快照
        subq = (
            select(
                ContentMetrics.publish_record_id,
                func.max(ContentMetrics.recorded_at).label("latest"),
            )
            .where(ContentMetrics.publish_record_id.in_(record_ids))
            .group_by(ContentMetrics.publish_record_id)
            .subquery()
        )
        metrics_stmt = (
            select(ContentMetrics, PublishRecord)
            .join(
                subq,
                (ContentMetrics.publish_record_id == subq.c.publish_record_id)
                & (ContentMetrics.recorded_at == subq.c.latest),
            )
            .join(PublishRecord, PublishRecord.id == ContentMetrics.publish_record_id)
            .order_by(getattr(ContentMetrics, sort_by).desc())
            .limit(limit)
        )
        result = await self.session.execute(metrics_stmt)
        rows = result.all()

        output = []
        for metrics, pr in rows:
            d = _metrics_to_dict(metrics)
            d["content_title"] = pr.content_title
            d["platform"] = pr.platform
            d["published_url"] = pr.published_url
            d["publish_record_id"] = pr.id
            output.append(d)
        return output


def _metrics_to_dict(m: ContentMetrics) -> dict:
    return {
        "id": m.id,
        "publish_record_id": m.publish_record_id,
        "recorded_at": m.recorded_at.isoformat() if m.recorded_at else None,
        "views": m.views,
        "likes": m.likes,
        "comments": m.comments,
        "shares": m.shares,
        "bookmarks": m.bookmarks,
        "ai_citation_count": m.ai_citation_count,
        "search_impressions": m.search_impressions,
        "search_clicks": m.search_clicks,
        "avg_read_duration": m.avg_read_duration,
        "read_completion_rate": m.read_completion_rate,
    }
