"""Tests for the postcode parser."""

import pytest

from tests.conftest import valid_postcodes
from wojtek.uk_postcodes.exceptions import InvalidPostcodeError
from wojtek.uk_postcodes.parser import parse_postcode


def test_can_parse_valid_postcodes(special_postcodes: set[str]) -> None:
    """Test that the parser can parse valid postcodes."""
    for postcode in valid_postcodes():
        postcode_object = parse_postcode(postcode)
        assert postcode_object.raw == postcode

    for postcode in special_postcodes:
        postcode_object = parse_postcode(postcode, allow_special=True)
        assert postcode_object.raw == postcode
        assert postcode_object.is_special is True


def test_parse_standard_postcode() -> None:
    """Ensure parsing returns structured data for standard postcodes."""
    standard_postcode = "SW1A 1AA"
    postcode = parse_postcode(standard_postcode)

    assert postcode.raw == standard_postcode
    assert postcode.outward == "SW1A"
    assert postcode.inward == "1AA"
    assert postcode.area == "SW"
    assert postcode.district == "1A"
    assert postcode.sector == "1"
    assert postcode.unit == "AA"
    assert postcode.is_special is False


def test_parse_special_postcode_when_allowed() -> None:
    """Ensure special postcodes parse when allowed."""
    special_postcode = "GIR 0AA"
    postcode = parse_postcode(special_postcode, allow_special=True)

    assert postcode.raw == special_postcode
    assert postcode.outward == "GIR"
    assert postcode.inward == "0AA"
    assert postcode.is_special is True


def test_parse_special_postcode_when_disallowed() -> None:
    """Ensure special postcodes fail when not allowed."""
    special_postcode = "GIR 0AA"
    with pytest.raises(InvalidPostcodeError):
        parse_postcode(special_postcode, allow_special=False)


def test_parse_invalid_postcode_raises() -> None:
    """Ensure malformed input raises a parser error."""
    with pytest.raises(InvalidPostcodeError):
        parse_postcode("12 123")
