import pytest

from app.core.mikrotik import MockMikrotikAdapter
from app.core.olt_adapters import (
    MockOLTAdapter,
    ONTDiscovery,
    UnsupportedOLTError,
    get_olt_adapter,
    supported_olt_adapters,
)
from app.core.provisioning import (
    provision_customer,
    suspend_customer_pppoe,
    unsuspend_customer_pppoe,
)
from app.models.models import Customer


def test_zte_c320_is_resolved_case_insensitively():
    adapter = get_olt_adapter(" zTe ", " c320 ")
    assert (adapter.vendor.lower(), adapter.model.lower()) == ("zte", "c320")
    assert any(item == {"vendor": "ZTE", "model": "C320"} for item in supported_olt_adapters())


def test_unknown_olt_is_blocked_safely():
    with pytest.raises(UnsupportedOLTError, match="tidak akan dikirimi konfigurasi"):
        get_olt_adapter("Huawei", "MA5608T")


def test_mock_olt_discovers_and_allocates_lowest_free_id():
    mock = MockOLTAdapter(
        onts={"ZTEGCC444066": ONTDiscovery("ZTEGCC444066", "ZTE", "1/1/1")},
        used_ids_by_port={"1/1/1": {1, 3}},
    )
    assert mock.discover_ont(" ztegcc444066 ").port == "1/1/1"
    assert mock.allocate_onu_id("1/1/1") == 2
    assert mock.allocate_onu_id("1/1/1") == 4


@pytest.mark.asyncio
async def test_provisioning_with_mocks_updates_discovery_and_secret():
    customer = Customer(
        ont_sn="ABC123", mikrotik_user="management", pppoe_username="cust",
        pppoe_password="secret", olt_vendor="ZTE", olt_model="C320",
    )
    olt = MockOLTAdapter(onts={"ABC123": ONTDiscovery("ABC123", "Huawei", "1/2/3")})
    mikrotik = MockMikrotikAdapter()
    result = await provision_customer(customer, olt_adapter=olt, mikrotik_adapter=mikrotik)
    assert result.olt_status == "simulated"
    assert result.mikrotik_status == "simulated"
    assert (customer.ont_brand, customer.olt_port, customer.onu_id) == ("Huawei", "1/2/3", 1)
    assert mikrotik.secrets["cust"]["service"] == "pppoe"


def test_suspend_and_unsuspend_mock_secret():
    customer = Customer(pppoe_username="cust")
    mock = MockMikrotikAdapter()
    mock.upsert_pppoe_secret("cust", "secret")
    suspend_customer_pppoe(customer, mock)
    assert mock.secrets["cust"]["disabled"] is True
    unsuspend_customer_pppoe(customer, mock)
    assert mock.secrets["cust"]["disabled"] is False


@pytest.mark.asyncio
async def test_default_provisioning_does_not_claim_hardware_success():
    customer = Customer(ont_sn="ABC123", mikrotik_user="management")
    result = await provision_customer(customer)
    assert result.olt_status == "not_configured"
    assert result.mikrotik_status == "not_configured"
    assert "tidak dijalankan" in result.message
