"""Periodic live-status reconciliation for Billing and customer views."""
import asyncio
import os

from sqlalchemy import select

from app.core.database import AsyncSessionLocal
from app.core.onboarding import refresh_customer_online_status
from app.models.models import Customer


def poll_interval() -> int:
    try:
        return max(10, int(os.getenv("BESTWEB_STATUS_POLL_SECONDS", "30")))
    except ValueError:
        return 30


async def monitor_loop() -> None:
    """Keep billing status aligned with live OLT/MikroTik state."""
    while True:
        try:
            async with AsyncSessionLocal() as db:
                customers = (await db.execute(
                    select(Customer).where(
                        Customer.is_archived == False,
                        Customer.pppoe_username.is_not(None),
                        Customer.mikrotik_device_id.is_not(None),
                        Customer.olt_device_id.is_not(None),
                    )
                )).scalars().all()
                for customer in customers:
                    try:
                        await refresh_customer_online_status(customer, db)
                    except Exception:
                        # One bad ONU must not prevent other customers from
                        # receiving a live status update in the same cycle.
                        await db.rollback()
        except asyncio.CancelledError:
            raise
        except Exception:
            # A device outage must not terminate the monitor permanently.
            pass
        await asyncio.sleep(poll_interval())
