"""Backward compatibility tests.

Verifies that the Ross1000 module does NOT break or modify:
- TXT export (istat/services.py)
- C59 XML export (istat/xml_export/)
- Guest XML export (istat/xml_export/)
- Existing URL patterns

These are smoke tests — they verify imports and URL registrations are intact,
not the full export logic (which is covered by the existing test suites).
"""

from __future__ import annotations

import importlib

import pytest


class TestTxtExportUnaffected:
    def test_istat_services_importable(self):
        """TXT export service must still be importable."""
        mod = importlib.import_module("istat.services")
        assert hasattr(mod, "generate_export_for_period")
        assert hasattr(mod, "generate_preview_for_period")
        assert hasattr(mod, "build_daily_calendar_for_date_range")

    def test_istat_services_has_bulk_fix(self):
        mod = importlib.import_module("istat.services")
        assert hasattr(mod, "apply_bulk_issue_fixes")


class TestC59ExportUnaffected:
    def test_c59_aggregation_service_importable(self):
        mod = importlib.import_module("istat.xml_export.services.c59_aggregation_service")
        assert hasattr(mod, "build_daily_c59_rows")
        assert hasattr(mod, "build_daily_c59_rows_for_structure")

    def test_c59_xml_serializer_importable(self):
        mod = importlib.import_module("istat.xml_export.serializers.c59_xml_serializer")
        assert hasattr(mod, "build_c59_xml_document")

    def test_c59_export_facade_importable(self):
        mod = importlib.import_module("istat.xml_export.application.export_facade")
        assert hasattr(mod, "generate_c59_xml_download")
        assert hasattr(mod, "generate_c59_zip_download")

    def test_c59_payload_model_importable(self):
        mod = importlib.import_module("istat.xml_export.models.c59_payload")
        assert hasattr(mod, "IstatC59RowPayload")


class TestGuestXmlExportUnaffected:
    def test_guest_xml_export_service_importable(self):
        mod = importlib.import_module("istat.xml_export.services.xml_export_service")
        assert hasattr(mod, "generate_guest_xml_export")

    def test_guest_payload_builder_importable(self):
        mod = importlib.import_module("istat.xml_export.builders.payload_builder")
        assert hasattr(mod, "build_guest_payload")

    def test_guest_normalization_importable(self):
        mod = importlib.import_module("istat.xml_export.services.guest_export_normalization")
        assert hasattr(mod, "normalize_guest_for_istat_export")
        assert hasattr(mod, "validate_guest_for_istat_export")


class TestIdswhSystemUnaffected:
    def test_guest_stay_model_importable(self):
        mod = importlib.import_module("guests.models")
        assert hasattr(mod, "GuestStay")

    def test_idswh_field_exists_on_guest_stay(self):
        from guests.models import GuestStay
        field_names = [f.name for f in GuestStay._meta.get_fields()]
        assert "idswh" in field_names

    def test_generate_idswh_function_importable(self):
        from guests.models import generate_idswh
        token = generate_idswh()
        assert isinstance(token, str)
        assert len(token) == 32


class TestExistingUrlsUnaffected:
    def test_istat_urls_importable(self):
        mod = importlib.import_module("istat.urls")
        assert hasattr(mod, "urlpatterns")

    def test_istat_export_url_still_present(self):
        from istat.urls import urlpatterns
        names = [p.name for p in urlpatterns if hasattr(p, "name")]
        assert "istat-export" in names

    def test_xml_export_urls_still_present(self):
        """The xml/ include must still be in istat/urls.py."""
        from istat.urls import urlpatterns
        # Find the include() for xml_export
        patterns_str = str(urlpatterns)
        assert "xml_export" in patterns_str or any(
            hasattr(p, "url_patterns") for p in urlpatterns
        )

    def test_ross1000_url_added_without_removing_others(self):
        from istat.urls import urlpatterns
        names = [p.name for p in urlpatterns if hasattr(p, "name")]
        # Original endpoints still present
        assert "istat-export" in names
        assert "istat-municipalities" in names


class TestRoss1000ModuleIsolated:
    def test_ross1000_does_not_import_txt_export_service(self):
        """Ross1000 module must not import from istat.services (TXT export)."""
        import ast
        import os

        ross1000_dir = os.path.join(
            os.path.dirname(__file__), ".."
        )
        forbidden_import = "istat.services"

        for root, dirs, files in os.walk(ross1000_dir):
            # Skip test files themselves
            if "tests" in root:
                continue
            for fname in files:
                if not fname.endswith(".py"):
                    continue
                fpath = os.path.join(root, fname)
                with open(fpath) as f:
                    source = f.read()
                try:
                    tree = ast.parse(source)
                except SyntaxError:
                    continue
                for node in ast.walk(tree):
                    if isinstance(node, ast.Import):
                        for alias in node.names:
                            assert forbidden_import not in alias.name, (
                                f"{fpath} imports from {forbidden_import} — "
                                "Ross1000 must not depend on TXT export service"
                            )
                    elif isinstance(node, ast.ImportFrom):
                        module = node.module or ""
                        assert not module.startswith(forbidden_import), (
                            f"{fpath} imports from {forbidden_import} — "
                            "Ross1000 must not depend on TXT export service"
                        )

    def test_ross1000_does_not_import_c59_serializer(self):
        """Ross1000 must not import from C59 XML serializer."""
        import ast
        import os

        ross1000_dir = os.path.join(os.path.dirname(__file__), "..")
        forbidden = "istat.xml_export.serializers.c59_xml_serializer"

        for root, dirs, files in os.walk(ross1000_dir):
            if "tests" in root:
                continue
            for fname in files:
                if not fname.endswith(".py"):
                    continue
                fpath = os.path.join(root, fname)
                with open(fpath) as f:
                    source = f.read()
                try:
                    tree = ast.parse(source)
                except SyntaxError:
                    continue
                for node in ast.walk(tree):
                    if isinstance(node, ast.ImportFrom):
                        module = node.module or ""
                        assert not module.startswith(forbidden), (
                            f"{fpath} imports from C59 serializer — "
                            "Ross1000 must be isolated"
                        )
