"""Periodic reconciliation for agent checkout and saved-card credit purchases."""

import structlog
from sqlalchemy import select

from src.config import get_settings
from src.domain.agent_access.dependencies import make_agent_service
from src.domain.agent_access.models import AgentOperation
from src.domain.agent_access.repository import AgentRepository
from src.domain.agent_access.service import utcnow
from src.domain.billing.agent_purchase_processor import AgentPurchaseProcessor
from src.integrations.agent_stripe import AgentStripe

log = structlog.get_logger()


async def reconcile_agent_purchases(ctx):
    settings = get_settings()
    if not settings.stripe_secret_key:
        return
    async with ctx["db_factory"]() as db:
        ids = list(
            (
                await db.scalars(
                    select(AgentOperation.id)
                    .where(
                        AgentOperation.action.in_(["purchase_credits", "create_credit_checkout"]),
                        AgentOperation.status.in_(["queued", "awaiting_payment"]),
                    )
                    .order_by(AgentOperation.updated_at)
                    .limit(25)
                )
            ).all()
        )
    stripe = AgentStripe(settings.stripe_secret_key)
    for operation_id in ids:
        try:
            async with ctx["db_factory"]() as db:
                async with db.begin():
                    row = (
                        await db.execute(
                            select(AgentOperation)
                            .where(
                                AgentOperation.id == operation_id,
                                AgentOperation.status.in_(["queued", "awaiting_payment"]),
                            )
                            .with_for_update(skip_locked=True)
                        )
                    ).scalar_one_or_none()
                    if not row:
                        continue
                    access = await make_agent_service(db)
                    grant = await access.repo.grant(row.grant_id, lock=True)
                    await AgentPurchaseProcessor(access, stripe).process(row, grant)
                    if row.status != "completed":
                        row.updated_at = utcnow()
        except Exception:
            log.warning("agent_payment_reconciliation_retry", operation_id=str(operation_id))
            try:
                async with ctx["db_factory"]() as retry_db:
                    async with retry_db.begin():
                        await AgentRepository(retry_db).defer_retry(operation_id, utcnow())
            except Exception:
                pass  # Database outage: durable rows remain available for the next scan.
