# app/analytics/tasks.py
from __future__ import annotations
from datetime import date, timedelta, datetime
from typing import Dict, Any
from celery import shared_task
from sqlalchemy import select
from src.utils.settings import settings
from src.utils.celery_app import celery
from src.marketing.apps.Account.model import ConnectedAccount, MasterAccount
from src.marketing.apps.Analytics.service import AnalyticsIngestionService
# Import async session directly from db.py to avoid circular imports
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker

from src.utils.settings import settings

# Create async engine just for workers (ORM, no raw SQL)
ASYNC_ENGINE = create_async_engine(settings.DATABASE_URL.replace("+psycopg2", "+asyncpg"), pool_pre_ping=True)
Session = async_sessionmaker(ASYNC_ENGINE, expire_on_commit=False)

def _yesterday() -> date:
    return date.today() - timedelta(days=1)

@celery.task(name="analytics.ingest_account_for_day", autoretry_for=(Exception,), retry_backoff=True, max_retries=5)
def ingest_account_for_day(connected_account_id: int, metric_date: str) -> Dict[str, Any]:
    import asyncio
    async def run():
        async with Session() as s:
            # load account + compose provider inputs from DB
            ca = await s.get(ConnectedAccount, connected_account_id)
            if not ca:
                return {"status":"skipped","reason":"no account"}
            ma = await s.get(MasterAccount, ca.master_account_id)
            network = (ma.social_media_name or "").lower()
            token_json = ca.token or {}
            account_ref = ca.permission or {}

            svc = AnalyticsIngestionService(s)
            return await svc.ingest_account_for_day(
                connected_account_id=connected_account_id,
                network=network,
                metric_date=metric_date,
                token_json=token_json,
                account_ref=account_ref
            )
    return asyncio.run(run())

@celery.task(name="analytics.ingest_all_accounts_daily", autoretry_for=(Exception,), retry_backoff=True, max_retries=3)
def ingest_all_accounts_daily(target_day: str | None = None) -> Dict[str, Any]:
    """
    Runs every morning after 02:00 UTC (post rate-limit friendly window).
    """
    import asyncio
    async def run():
        d = datetime.strptime(target_day, "%Y-%m-%d").date() if target_day else _yesterday()
        async with Session() as s:
            stmt = select(ConnectedAccount).where((ConnectedAccount.is_deleted.is_(False)) | (ConnectedAccount.is_deleted.is_(None)))
            res = await s.execute(stmt)
            accounts = res.scalars().all()

            ok, skipped = 0, 0
            for ca in accounts:
                out = await AnalyticsIngestionService(s).ingest_account_for_day(
                    connected_account_id=ca.id,
                    network=(await s.get(MasterAccount, ca.master_account_id)).social_media_name.lower(),
                    metric_date=d,
                    token_json=ca.token or {},
                    account_ref=ca.permission or {}
                )
                if out.get("status") == "ok":
                    ok += 1
                else:
                    skipped += 1
            return {"date": d.isoformat(), "ok": ok, "skipped": skipped}
    return asyncio.run(run())
