"""Background task: refresh login subscription IPs every 2 hours.

Data model:
  login_subscription_url  — URL to fetch (configurable in settings)
  login_subscription_ips  — IPs from last fetch (completely replaced each time)
  login_manual_ips        — manually added (never touched by auto-refresh)
  login_allowed_ips       — combined: subscription + manual (used by auth check)
  login_allowlist_enabled — "true" / "false" master switch
"""

import asyncio
import logging

logger = logging.getLogger("nexus.ip_allowlist_refresh")

REFRESH_INTERVAL = 7200   # 2 hours
_last_refresh_at: str = ""
_last_subscription_count: int = 0


async def ip_allowlist_refresh_loop():
    """Every 2 hours, re-fetch subscription IPs and rebuild combined allowlist."""
    logger.info("IP allowlist refresh loop started (interval=%sh)", REFRESH_INTERVAL // 3600)
    # Initial refresh shortly after startup
    await asyncio.sleep(5)
    await _do_refresh()
    while True:
        await asyncio.sleep(REFRESH_INTERVAL)
        await _do_refresh()


async def _do_refresh():
    """Fetch subscription, replace subscription IPs, rebuild combined list."""
    global _last_refresh_at, _last_subscription_count
    from server.config import settings
    from server.infrastructure.subscription_parser import parse_subscription_content

    sub_url = (settings.LOGIN_SUBSCRIPTION_URL or "").strip()
    if not sub_url:
        return

    logger.info("Refreshing subscription IPs from: %s", sub_url[:80])
    try:
        import httpx
        async with httpx.AsyncClient(timeout=20.0) as client:
            resp = await client.get(sub_url, follow_redirects=True)
        if resp.status_code != 200:
            logger.warning("Subscription returned HTTP %s", resp.status_code)
            return
        new_sub_ips = parse_subscription_content(resp.text)
    except Exception as e:
        logger.error("Subscription fetch failed: %s", e)
        return

    # Manual IPs (always preserved)
    manual_raw = (settings.LOGIN_MANUAL_IPS or "").strip()
    manual_ips = [ip.strip() for ip in manual_raw.split(",") if ip.strip()]

    # Combined list: subscription first, then manual (dedup)
    seen: set[str] = set()
    combined: list[str] = []
    for ip in new_sub_ips + manual_ips:
        if ip not in seen:
            seen.add(ip)
            combined.append(ip)

    sub_val = ",".join(new_sub_ips)
    combined_val = ",".join(combined)

    try:
        from server.infrastructure.database.session import AsyncSessionLocal
        from server.infrastructure.database.setting_repo import SettingRepositoryImpl
        async with AsyncSessionLocal() as session:
            repo = SettingRepositoryImpl(session)
            # Subscription IPs — replaced entirely
            await repo.set("login_subscription_ips", sub_val)
            # Combined — for auth check
            await repo.set("login_allowed_ips", combined_val)

        settings.LOGIN_SUBSCRIPTION_IPS = sub_val
        settings.LOGIN_ALLOWED_IPS = combined_val

        from datetime import datetime, timezone
        _last_refresh_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
        _last_subscription_count = len(new_sub_ips)
        logger.info(
            "Subscription IPs refreshed: %d → combined %d (+ %d manual)",
            len(new_sub_ips), len(combined), len(manual_ips),
        )
    except Exception as e:
        logger.error("Failed to save subscription IPs: %s", e)


def get_last_refresh_time() -> str:
    return _last_refresh_at


def get_subscription_count() -> int:
    return _last_subscription_count
