import asyncio
import logging
import datetime as dt
from sqlalchemy import select

from ..db import AsyncSessionLocal
from ..models import AutofillPolicy

log = logging.getLogger(__name__)


async def _tick_c2a(pol: AutofillPolicy) -> None:
    """Run a C2A pass and safe-apply for one tenant according to policy."""
    # Import lazily to avoid circular imports
    from ..api.v2.c2a import RunBody, c2a_run, c2a_safe_apply
    from ..services.salesforce_gateway import get_salesforce_gateway

    async with AsyncSessionLocal() as db:
        # Start a job over tenant scope (let service determine scan windows)
        body = RunBody(
            threshold=float(pol.c2a_threshold or 0.80),
            b2c_skip=bool(pol.b2c_skip),
            mode="assign",
            sample_limit=None,
            contact_ids=None,
        )
        try:
            _ = await c2a_run(
                body=body,
                db=db,
                account_id=str(pol.account_id),
                user_id="autofill-daemon",
            )
        except Exception:
            log.exception("autofill c2a_run failed for %s", pol.account_id)
        await asyncio.sleep(0)

        # Safe-apply high-confidence suggestions
        try:
            sf = await get_salesforce_gateway()
            _res = await c2a_safe_apply(
                min_score=float(pol.c2a_threshold or 0.80),
                writeback_mode=str(pol.c2a_writeback_mode or "account"),
                db=db,
                account_id=str(pol.account_id),
                sf=sf,
            )
        except Exception:
            log.exception("autofill c2a_safe_apply failed for %s", pol.account_id)

        # Update cursor
        try:
            pol.c2a_last_run = dt.datetime.utcnow()
            db.add(pol)
            await db.commit()
        except Exception:
            await db.rollback()


async def tick_once() -> None:
    """Run one autofill sweep across all tenants with enabled policies.

    Currently supports C2A; L2A can be added similarly when a safe-apply helper exists.
    """
    async with AsyncSessionLocal() as db:
        rows = (await db.execute(select(AutofillPolicy))).scalars().all()
        for pol in rows or []:
            try:
                if bool(getattr(pol, "c2a_enabled", False)):
                    await _tick_c2a(pol)
                if bool(getattr(pol, "l2a_enabled", False)):
                    await _tick_l2a(pol)
            except Exception:
                log.exception(
                    "autofill tick failed for %s", getattr(pol, "account_id", "?")
                )


async def _tick_l2a(pol: AutofillPolicy) -> None:
    """Run an L2A suggestions pass then safe-apply for one tenant.

    This reuses IntelligentL2AService to generate suggestions, then applies
    high-confidence ones via the l2a_safe_apply helper.
    """
    from ..api.v2.l2a import l2a_safe_apply
    from ..services.l2a_service_intelligent import IntelligentL2AService
    from ..models import Integration, IntegrationProvider, IntegrationStatus
    from ..services.salesforce_gateway import get_salesforce_gateway
    import datetime as _dt

    async with AsyncSessionLocal() as db:
        # Ensure Salesforce integration exists and is connected
        integ = (
            await db.execute(
                select(Integration).where(
                    Integration.account_id == str(pol.account_id),
                    Integration.provider == IntegrationProvider.SALESFORCE,
                    Integration.status == IntegrationStatus.CONNECTED,
                )
            )
        ).scalar_one_or_none()
        if not integ:
            log.info("autofill L2A: no connected Salesforce for %s", pol.account_id)
            return

        svc = IntelligentL2AService(db, str(pol.account_id))
        # Ensure policy exists (creates if missing)
        try:
            await svc.ensure_policy(str(pol.account_id), integ.id)
        except Exception:
            log.exception("autofill L2A: ensure_policy failed for %s", pol.account_id)
            return

        # Map scope -> created_date_from
        created_date_from = None
        try:
            if (pol.scope or "new_only") == "new_only":
                hours = int(pol.new_window_hours or 48)
                dt_from = _dt.datetime.utcnow() - _dt.timedelta(hours=hours)
                created_date_from = dt_from.strftime(
                    "%Y-%m-%d"
                )  # service accepts YYYY-MM-DD
        except Exception:
            created_date_from = None

        # Run discovery/generation
        def _progress(pct: float, msg: str = ""):
            try:
                log.debug("autofill L2A %s: %.0f%% %s", pol.account_id, pct * 100, msg)
            except Exception:
                pass

        try:
            await svc.run(
                str(pol.account_id),
                threshold_override=float(pol.l2a_threshold or 0.80),
                progress_cb=_progress,
                created_date_from=created_date_from,
                mode="incremental",
            )
        except Exception:
            log.exception("autofill L2A: service run failed for %s", pol.account_id)
            return

        # Safe-apply suggestions
        try:
            sf = await get_salesforce_gateway()
            _ = await l2a_safe_apply(
                min_score=float(pol.l2a_threshold or 0.80),
                db=db,
                account_id=str(pol.account_id),
                user_id="autofill-daemon",
                sf=sf,
            )
        except Exception:
            log.exception("autofill L2A: safe-apply failed for %s", pol.account_id)
            return

        # Update cursor
        try:
            pol.l2a_last_run = _dt.datetime.utcnow()
            db.add(pol)
            await db.commit()
        except Exception:
            await db.rollback()
