"""Database-only network selection helpers used by installation forms."""

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.models import Customer, VlanMappingRule

DEFAULT_VLAN_MAPPINGS = {175: 15, 172: 10}


def map_vlan(source_vlan: int, purpose: str = "service", rules=None) -> int:
    """Map a service VLAN without contacting an OLT or MikroTik device."""
    if rules is None:
        rules = DEFAULT_VLAN_MAPPINGS
    if isinstance(rules, dict):
        return int(rules.get(int(source_vlan), source_vlan))
    for rule in rules:
        if rule.source_vlan == source_vlan and rule.purpose == purpose and rule.is_active:
            return rule.target_vlan
    return int(source_vlan)


async def map_vlan_from_db(session: AsyncSession, source_vlan: int, purpose: str = "service") -> int:
    rule = await session.scalar(
        select(VlanMappingRule).where(
            VlanMappingRule.source_vlan == source_vlan,
            VlanMappingRule.purpose == purpose,
            VlanMappingRule.is_active.is_(True),
        )
    )
    return rule.target_vlan if rule else map_vlan(source_vlan, purpose)


async def lowest_free_onu_id(
    session: AsyncSession,
    olt_port: str,
    start: int = 1,
    end: int = 128,
) -> int | None:
    """Return the lowest ONU ID not present for *olt_port*.

    This is intentionally a pure database read. Callers should run it and the
    subsequent Customer insert in one transaction; no hardware is contacted.
    """
    if start < 1 or end < start:
        raise ValueError("ONU ID range tidak valid")
    result = await session.scalars(
        select(Customer.onu_id).where(
            Customer.olt_port == olt_port,
            Customer.onu_id >= start,
            Customer.onu_id <= end,
        )
    )
    used = set(result.all())
    return next((onu_id for onu_id in range(start, end + 1) if onu_id not in used), None)


find_lowest_free_onu_id = lowest_free_onu_id
