#!/usr/bin/env python3

# IBAN length dictionary
IBAN_LENGTHS = {
    'AT': 20,  # Austria
    'DE': 22,  # Germany
    'CH': 21,  # Switzerland
}

# Check the length of the IBAN
def check_iban_length(iban):
    country_code = iban[:2]
    if country_code not in IBAN_LENGTHS:
        print(f'Error: Country code {country_code} not found')
        return False
    if len(iban) != IBAN_LENGTHS[country_code]:
        print(f'Error: IBAN length is incorrect for {country_code}')
        return False
    return True

# Remove spaces and convert to uppercase
def tidy_iban(iban):
    return iban.replace(' ', '').upper()

# Test the checksum
def test_checksum(iban):
    # Rearrange IBAN and convert letters to numbers
    iban_rearranged = iban[4:] + iban[:4]
    digit_string = ''.join(str(ord(c) - 55) if c.isalpha() else c for c in iban_rearranged)
    # Convert the string to an integer and test if modulo 97 is 1
    try:
        return int(digit_string) % 97 == 1
    except ValueError:
        print('Error: Non-numeric value encountered during checksum calculation')
        return False

# Verify the IBAN
def verify_iban(iban):
    iban = tidy_iban(iban)
    return check_iban_length(iban) and test_checksum(iban)

# Test code
def test_iban_validation():
    valid_ibans = [
        'AT611904300234573201', 'AT483200000012345864', 'AT477604026440308794',
        'DE89370400440532013000', 'DE44500105175407324931', 'DE75512108001245126199',
        'CH9300762011623852957', 'CH5604835012345678009'
    ]
    invalid_ibans = [
        'AT61190430023457320', 'AT12345678901234567890', 'AT6119040000003201111',
        'DE8937040044053201300', 'DE12345678901234567890', 'DE445001051754073249311',
        'CH930076201162385295', 'CH12345678901234567890', 'CH56048350123456780091'
    ]
    
    for iban in valid_ibans:
        assert verify_iban(iban), f"Error: Valid IBAN failed: {iban}"
    
    for iban in invalid_ibans:
        assert not verify_iban(iban), f"Error: Invalid IBAN passed: {iban}"
    
    print("All tests passed!")

# Main code
if __name__ == "__main__":
    test_iban_validation()
