"""
Background job to poll ad campaign metrics from all platforms
and auto-complete expired campaigns.

Usage:
    python -m app.ads.metrics_worker          # one-shot
    python -m app.ads.metrics_worker --loop   # continuous (every 30 min)
"""
import asyncio
import sys
import time
import logging
from datetime import datetime, date, timedelta

logger = logging.getLogger(__name__)


def poll_all_metrics(app=None):
    """Fetch latest metrics for every active ad campaign."""
    if app is None:
        from app import create_app
        app = create_app()

    with app.app_context():
        from app.extensions import db
        from app.models.ads import (
            AdCampaign, AdCampaignMetrics, AdminAdAccount,
            AdBudgetWallet, UserAdBudget, AdAuditLog
        )
        from app.ads import get_ad_platform
        from app.ai.diamond import run_sync

        active_campaigns = AdCampaign.query.filter(
            AdCampaign.status.in_(["active"])
        ).all()

        logger.info(f"Polling metrics for {len(active_campaigns)} active campaigns")

        for ad_camp in active_campaigns:
            platform_ids = ad_camp.platform_ids_json or {}

            for platform_name, ids_data in platform_ids.items():
                if not isinstance(ids_data, dict) or ids_data.get("error"):
                    continue

                platform_campaign_id = ids_data.get("campaign_id")
                if not platform_campaign_id:
                    continue

                account = AdminAdAccount.query.filter_by(
                    platform=platform_name, is_active=True
                ).first()
                if not account:
                    continue

                try:
                    ad_platform = get_ad_platform(platform_name)
                    date_from = (datetime.utcnow() - timedelta(days=2)).strftime("%Y-%m-%d")
                    date_to = datetime.utcnow().strftime("%Y-%m-%d")

                    metrics_list = run_sync(
                        ad_platform.get_metrics(platform_campaign_id, account, date_from, date_to)
                    )

                    for m_data in metrics_list:
                        m_date = m_data.get("date", "")
                        if not m_date:
                            continue
                        try:
                            if isinstance(m_date, str):
                                m_date_obj = datetime.strptime(m_date[:10], "%Y-%m-%d").date()
                            else:
                                m_date_obj = m_date
                        except (ValueError, TypeError):
                            continue

                        existing = AdCampaignMetrics.query.filter_by(
                            ad_campaign_id=ad_camp.id,
                            platform=platform_name,
                            date=m_date_obj,
                        ).first()

                        if existing:
                            existing.impressions = m_data.get("impressions", 0)
                            existing.views = m_data.get("views", 0)
                            existing.clicks = m_data.get("clicks", 0)
                            existing.ctr = m_data.get("ctr", 0)
                            existing.spend = m_data.get("spend", 0)
                            existing.cost_per_view = m_data.get("cost_per_view", 0)
                            existing.cost_per_click = m_data.get("cost_per_click", 0)
                            existing.likes = m_data.get("likes", 0)
                            existing.comments = m_data.get("comments", 0)
                            existing.shares = m_data.get("shares", 0)
                            existing.reach = m_data.get("reach", 0)
                            existing.frequency = m_data.get("frequency", 0)
                            existing.fetched_at = datetime.utcnow()
                        else:
                            metric = AdCampaignMetrics(
                                ad_campaign_id=ad_camp.id,
                                platform=platform_name,
                                date=m_date_obj,
                                impressions=m_data.get("impressions", 0),
                                views=m_data.get("views", 0),
                                clicks=m_data.get("clicks", 0),
                                ctr=m_data.get("ctr", 0),
                                spend=m_data.get("spend", 0),
                                cost_per_view=m_data.get("cost_per_view", 0),
                                cost_per_click=m_data.get("cost_per_click", 0),
                                likes=m_data.get("likes", 0),
                                comments=m_data.get("comments", 0),
                                shares=m_data.get("shares", 0),
                                reach=m_data.get("reach", 0),
                                frequency=m_data.get("frequency", 0),
                            )
                            db.session.add(metric)

                    logger.info(f"  [OK] {ad_camp.name} / {platform_name}: {len(metrics_list)} rows")

                except Exception as e:
                    logger.warning(f"  [FAIL] {ad_camp.name} / {platform_name}: {e}")

            # Auto-complete expired campaigns
            if ad_camp.end_date and ad_camp.end_date <= datetime.utcnow():
                ad_camp.status = "completed"
                log = AdAuditLog(
                    ad_campaign_id=ad_camp.id,
                    user_id=ad_camp.user_id,
                    action="completed",
                    details_json={"reason": "auto_expired"},
                )
                db.session.add(log)

                # Notify user
                try:
                    from app.models.features import Notification
                    notif = Notification(
                        user_id=ad_camp.user_id,
                        title="اكتمال حملة إعلانية",
                        message=f"اكتملت حملتك الإعلانية: {ad_camp.name}",
                        category="ads",
                    )
                    db.session.add(notif)
                except Exception:
                    pass

                logger.info(f"  [COMPLETED] {ad_camp.name} (expired)")

            # Budget overspend check
            actual_spend = ad_camp.total_spend
            if actual_spend >= ad_camp.budget_amount * 0.9 and ad_camp.status == "active":
                try:
                    from app.models.features import Notification
                    notif = Notification(
                        user_id=ad_camp.user_id,
                        title="تنبيه ميزانية",
                        message=f"تنبيه: حملتك «{ad_camp.name}» استهلكت {int(actual_spend / ad_camp.budget_amount * 100)}% من الميزانية.",
                        category="ads",
                    )
                    db.session.add(notif)
                except Exception:
                    pass

        db.session.commit()
        logger.info("Metrics polling complete.")


def run_loop(interval_seconds=1800):
    """Run metrics polling in a loop."""
    from app import create_app
    app = create_app()
    logger.info(f"Starting metrics worker loop (interval: {interval_seconds}s)")
    while True:
        try:
            poll_all_metrics(app)
        except Exception as e:
            logger.error(f"Metrics worker error: {e}")
        time.sleep(interval_seconds)


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
    if "--loop" in sys.argv:
        run_loop()
    else:
        poll_all_metrics()
