"""Login IP allowlist helpers (shared by auth API precheck and AuthService.login)."""

from __future__ import annotations

import ipaddress

from server.config import settings

_TRUTHY = frozenset({"true", "1", "yes", "on"})


def is_allowlist_enforced() -> bool:
    """Whether LOGIN_ALLOWLIST_ENABLED is on."""
    val = (getattr(settings, "LOGIN_ALLOWLIST_ENABLED", "false") or "false").lower()
    return val in _TRUTHY


def get_allowed_login_ips() -> list[str]:
    """Combined subscription + manual IPs from settings."""
    sub_ips_raw = (getattr(settings, "LOGIN_SUBSCRIPTION_IPS", "") or "").strip()
    manual_ips_raw = (getattr(settings, "LOGIN_MANUAL_IPS", "") or "").strip()
    all_ips_raw = ",".join(filter(None, [sub_ips_raw, manual_ips_raw]))
    return [ip.strip() for ip in all_ips_raw.split(",") if ip.strip()]


def ip_in_allowlist(client_ip: str, allowed: list[str]) -> bool:
    """Check if client_ip matches any entry in the allowlist."""
    try:
        client_addr = ipaddress.ip_address(client_ip)
        for entry in allowed:
            entry = entry.strip()
            try:
                if "/" in entry:
                    if client_addr in ipaddress.ip_network(entry, strict=False):
                        return True
                elif client_addr == ipaddress.ip_address(entry):
                    return True
            except ValueError:
                if client_ip == entry:
                    return True
    except ValueError:
        return client_ip in allowed
    return False


def check_login_ip(client_ip: str) -> tuple[bool, bool, str | None]:
    """Evaluate login IP access.

    Returns:
        (allowlist_enabled, allowed, message)
        - allowlist off: (False, True, None)
        - allowlist on, empty list: (True, True, None) — nothing to enforce
        - allowlist on, IP ok: (True, True, None)
        - allowlist on, IP blocked: (True, False, message)
    """
    if not is_allowlist_enforced():
        return False, True, None

    if not client_ip or client_ip in ("", "unknown"):
        return True, True, None

    allowed_ips = get_allowed_login_ips()
    if not allowed_ips:
        return True, True, None

    if ip_in_allowlist(client_ip, allowed_ips):
        return True, True, None

    return (
        True,
        False,
        f"当前 IP ({client_ip}) 不在登录白名单中，请检查代理或联系管理员",
    )


def is_whitelisted_login_ip(client_ip: str) -> bool:
    """True when allowlist is enforced, non-empty, and client IP matches."""
    if not is_allowlist_enforced():
        return False
    if not client_ip or client_ip in ("", "unknown"):
        return False
    allowed_ips = get_allowed_login_ips()
    return bool(allowed_ips) and ip_in_allowlist(client_ip, allowed_ips)
