import pytest

from backend.addresses.Addresses import Addresses


# -------------------------
# Helpers
# -------------------------

class AraBody:
    file_format = "ara_property_list"


class LegacyBody:
    file_format = "legacy"


# -------------------------
# ARA FORMAT TESTS
# -------------------------

def test_parse_ara_row_valid():
    row = {
        "uprn": "123",
        "address_1": "10 Downing St",
        "full_address": "10 Downing St, London",
        "postcode": "SW1A 2AA",
    }

    addresses = Addresses.from_plan_input([row], AraBody())

    assert len(addresses) == 1
    addr = addresses[0]

    assert addr.uprn == 123
    assert addr.address_1 == "10 Downing St"
    assert addr.full_address == "10 Downing St, London"
    assert addr.postcode == "SW1A 2AA"


def test_parse_ara_row_optional_fields():
    row = {
        "uprn": "456",
        "address_1": "Flat 2",
        "full_address": "Flat 2, Test House",
        "postcode": "AB1 2CD",
        "landlord_property_id": "ABC123",
    }

    addresses = Addresses.from_plan_input([row], AraBody())
    addr = addresses[0]

    assert addr.uprn == 456
    assert addr.landlord_property_id == "ABC123"


# -------------------------
# LEGACY FORMAT TESTS
# -------------------------

def test_parse_legacy_basic():
    row = {
        "landlord_property_id": 144002000000,
        "address": "15 Rosebank Hall Angle Terrace",
        "postcode": "NE28 7BQ",
        "ordnance_survey_uprn": 47002793,
        "property_type": "Bungalow",
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    addr = addresses[0]

    assert addr.uprn == 47002793
    assert addr.address_1 == "15 Rosebank Hall Angle Terrace"
    assert addr.postcode == "NE28 7BQ"
    assert addr.landlord_property_type == "Bungalow"


def test_legacy_uses_domna_address_if_missing_address():
    row = {
        "domna_address_1": "Domna Address",
        "postcode": "AA1 1AA",
        "ordnance_survey_uprn": 123456,
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    addr = addresses[0]

    assert addr.address_1 == "Domna Address"


def test_legacy_full_address_fallback():
    row = {
        "address": "Fallback Address",
        "postcode": "ZZ1 1ZZ",
        "ordnance_survey_uprn": 999,
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    addr = addresses[0]

    assert addr.full_address == "Fallback Address"


# -------------------------
# UPRN HANDLING
# -------------------------

def test_uprn_from_float_string():
    row = {
        "uprn": "123.0",
        "address": "Test Address",
        "postcode": "AA1 1AA",
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    assert addresses[0].uprn == 123


def test_uprn_fallback_to_os_uprn():
    row = {
        "uprn": None,
        "ordnance_survey_uprn": 555,
        "address": "Test Address",
        "postcode": "AA1 1AA",
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    assert addresses[0].uprn == 555


def test_missing_uprn_is_none():
    row = {
        "address": "No UPRN Address",
        "postcode": "BB1 1BB",
    }

    addresses = Addresses.from_plan_input([row], LegacyBody())
    assert addresses[0].uprn is None


# -------------------------
# FALLBACK LOGIC
# -------------------------

def test_fallback_to_legacy_when_ara_fails():
    """
    If ARA parser fails (missing required fields),
    system should fallback to legacy parser.
    """
    row = {
        "address": "Fallback Address",
        "postcode": "ZZ1 1ZZ",
    }

    addresses = Addresses.from_plan_input([row], AraBody())
    addr = addresses[0]

    assert addr.address_1 == "Fallback Address"


# -------------------------
# VALIDATION
# -------------------------

def test_validate_uprn_rejects_invalid():
    row = {
        "uprn": "not_a_number",
        "address_1": "Test",
        "full_address": "Test",
        "postcode": "AA1 1AA",
    }

    with pytest.raises(ValueError):
        Addresses.from_plan_input([row], AraBody())


# -------------------------
# COLLECTION METHODS
# -------------------------

def test_get_uprns():
    rows = [
        {"uprn": "1", "address_1": "A", "full_address": "A", "postcode": "AA"},
        {"uprn": "2", "address_1": "B", "full_address": "B", "postcode": "BB"},
    ]

    addresses = Addresses.from_plan_input(rows, AraBody())
    assert addresses.get_uprns() == [1, 2]


def test_get_unique_postcodes():
    rows = [
        {"uprn": "1", "address_1": "A", "full_address": "A", "postcode": "AA"},
        {"uprn": "2", "address_1": "B", "full_address": "B", "postcode": "AA"},
    ]

    addresses = Addresses.from_plan_input(rows, AraBody())
    assert addresses.get_unique_postcodes() == ["AA"]


def test_get_property_requests():
    row = {
        "uprn": "123",
        "address_1": "10 Downing St",
        "full_address": "10 Downing St",
        "postcode": "SW1A 2AA",
    }

    addresses = Addresses.from_plan_input([row], AraBody())
    request = addresses.get_property_requests()[0]

    assert request["uprn"] == 123
    assert request["postcode"] == "SW1A 2AA"
