import unittest

from account.forms import OrganizationForm


class CleanKvkNumberTests(unittest.TestCase):
    # pylint: disable=invalid-name
    def test_clean_kvk_number_happy_paths(self):
        # Arrange
        cases = [
            {
                "id": "happy-all-different-digits",
                "kvk_input": "12345678",
                "expected_output": "12345678",
            },
            {
                "id": "happy-all-zeros",
                "kvk_input": "00000000",
                "expected_output": "00000000",
            },
            {
                "id": "happy-random-valid",
                "kvk_input": "98765432",
                "expected_output": "98765432",
            },
        ]

        for case in cases:
            with self.subTest(case_id=case["id"]):

                # Arrange
                data = {
                    "name": f"Test Org {case['id']}",
                    "slug": f"test-org-{case['id']}",
                    "kvk_number": case["kvk_input"]
                }
                form = OrganizationForm(data=data)

                # Act
                is_valid = form.is_valid()
                kvk_cleaned = form.cleaned_data.get("kvk_number") if is_valid else None

                # Assert
                self.assertTrue(is_valid, f"Form errors: {form.errors}")
                self.assertEqual(kvk_cleaned, case["expected_output"])

    # pylint: disable=invalid-name
    def test_clean_kvk_number_edge_cases(self):
        # Arrange
        cases = [
            {
                "id": "edge-none-value",
                "data": {"kvk_number": None},
                "expected_output": None,
            },
            {
                "id": "edge-empty-string",
                "data": {"kvk_number": ""},
                "expected_output": None,
            },
        ]

        for case in cases:
            with self.subTest(case_id=case["id"]):

                # Arrange
                form = OrganizationForm(data=case["data"])
                print(case['id'])
                # Act
                is_valid = form.is_valid()
                kvk_cleaned = form.cleaned_data.get("kvk_number") if is_valid else None

                # Assert
                self.assertFalse(is_valid)
                self.assertEqual(kvk_cleaned, case["expected_output"])

    # pylint: disable=invalid-name
    def test_clean_kvk_number_error_cases(self):
        # Arrange
        cases = [
            {
                "id": "error-too-short-7-digits",
                "kvk_input": "1234567",
            },
            {
                "id": "error-too-long-9-digits",
                "kvk_input": "123456789",
            },
            {
                "id": "error-letters-only",
                "kvk_input": "ABCDEFGH",
            },
            {
                "id": "error-mixed-alnum",
                "kvk_input": "1234ABCD",
            },
            {
                "id": "error-space-in-string",
                "kvk_input": "1234 678",
            },
            {
                "id": "error-hyphen-in-string",
                "kvk_input": "1234-678",
            },
            {
                "id": "error-non-ascii-digits",
                "kvk_input": "１２３４５６７８",
            },
        ]
        expected_error = "Een KvK-nummer moet precies 8 cijfers bevatten."

        for case in cases:
            with self.subTest(case_id=case["id"]):

                # Arrange
                form = OrganizationForm(data={"kvk_number": case["kvk_input"]})

                # Act
                is_valid = form.is_valid()
                errors = form.errors.get("kvk_number", [])

                # Assert
                self.assertFalse(is_valid)
                self.assertIn(expected_error, errors)


if __name__ == "__main__":
    unittest.main()
