#!/usr/bin/env python3
# Copyright: 2026, Maximiliano Curia <maxy@debian.org>
#
# License: ISC
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#  .
#  THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
#  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
#  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  PERFORMANCE OF THIS SOFTWARE.

"""
Integration test for core types functionality

This test verifies that all modules can work together after the
core_types extraction and import updates. It exercises the full flow:
options -> tree -> dep5 -> output.
"""

import io
import tempfile
import unittest
from contextlib import redirect_stdout
from pathlib import Path

from decopy import cmdoptions, dep5, output, tree


class TestCoreTypesIntegration(unittest.TestCase):
    """Test integration of core_types with all modules."""

    def setUp(self):
        """Set up test environment."""
        self.temp_dir = tempfile.mkdtemp()
        self.temp_path = Path(self.temp_dir)

        # Create a simple test directory structure
        (self.temp_path / "src").mkdir()
        (self.temp_path / "debian").mkdir()

        # Create some test files
        (self.temp_path / "src" / "main.py").write_text("# Test file")
        (self.temp_path / "src" / "utils.py").write_text("# Test file")
        (self.temp_path / "debian" / "rules").write_text("# Debian rules")
        (self.temp_path / "debian" / "compat").write_text("11")
        (self.temp_path / "COPYING").write_text("# GPL License\n")

    def tearDown(self):
        """Clean up test environment."""
        import shutil

        shutil.rmtree(self.temp_dir)

    def test_full_integration_flow(self):
        """Test the full flow: options → tree → dep5 → output."""
        # Step 1: Create options
        options = cmdoptions.process_options(
            ["--no-progress", "--root", str(self.temp_path), "--mode", "full"],
        )

        # Test that options uses core_types Options
        from decopy.core_types import Options

        self.assertIsInstance(options, Options)

        # Step 2: Build tree
        filetree = tree.RootInfo.build(options)

        # Verify tree structure
        self.assertIn("", filetree.names)  # Root directory
        self.assertIn("src", filetree.names)
        self.assertIn("debian", filetree.names)

        # Step 3: Process tree (this will parse files and detect licenses/copyrights)
        filetree.process(options)

        # Verify that files have been processed
        main_py = filetree["src/main.py"]
        self.assertTrue(main_py.included)

        # Step 4: Build copyright info
        copyright_ = dep5.Copyright.build(filetree, options)

        # Process copyright matching
        copyright_.process(filetree)
        copyright_.remove_misplaced_files(options)

        # Get groups for output
        groups = copyright_.get_group_dict(options)

        # Step 5: Generate output

        # Test output generation
        with redirect_stdout(io.StringIO()) as output_buffer:
            output.generate_output(groups, filetree, copyright_, options)

        # Get the captured output
        output_text = output_buffer.getvalue()

        # Verify output was generated
        self.assertTrue(len(output_text) > 0)

        # Check that output contains expected elements
        self.assertIn("Format:", output_text)  # Header should be present
        self.assertIn("Source:", output_text)  # Source should be present

    def test_module_imports_together(self):
        """Test that all modules can be imported together without conflicts."""
        # This should work without any circular import issues
        from decopy import (  # noqa: F401
            cmdoptions,
            core_types,
            dep5,
            licenses,
            output,
            re_types,  # Still available as importer
            res,
            tree,
        )

        # Test that core_types classes are available
        from decopy.core_types import CopyrightHolder, License, Options, YearRange

        # Test basic functionality of all imported classes
        license_obj = License.get("GPL-2+")
        years = YearRange(2020, 2023)
        holder = CopyrightHolder("Test Name", "test@example.com", years)
        options = Options(
            mode="full",
            copyright_file="debian/copyright",
            debug=False,
            text=False,
            group_by="license",
            split_on_license=True,
            split_debian=False,
            glob=True,
            progress=False,
            jobs=1,
            output="",
            root=".",
            files=[],
            exclude_fullname_re=res.rex.compile(r".*"),
            exclude_special_re=res.rex.compile(r".*"),
            exclude_file_re=res.rex.compile(r".*"),
            exclude_directory_re=res.rex.compile(r".*"),
        )

        # Verify all objects work correctly
        self.assertEqual(license_obj.name, "GPL-2+")
        self.assertEqual(str(years), "2020-2023")
        self.assertEqual(holder.name, "Test Name")
        self.assertEqual(options.mode, "full")

    def test_no_circular_imports(self):
        """Test that no circular imports exist between modules."""
        # Import all modules in different orders to detect circular imports
        import_modules = [
            "decopy.cmdoptions",
            "decopy.core_types",
            "decopy.dep5",
            "decopy.licenses",
            "decopy.output",
            "decopy.re_types",
            "decopy.res",
            "decopy.tree",
        ]

        # Try importing in different orders
        for order in [
            import_modules,
            reversed(import_modules),
            sorted(import_modules),
            sorted(import_modules, reverse=True),
        ]:
            try:
                for module_name in order:
                    __import__(module_name)
            except ImportError as e:
                if "circular" in str(e).lower():
                    self.fail(f"Circular import detected: {e}")
                # Re-raise if it's not a circular import issue
                raise

    def test_constants_available(self):
        """Test that constants are available from core_types."""
        from decopy.core_types import UNKNOWN, UNKNOWN_COPYRIGHTED

        # Test constants have correct values
        self.assertEqual(UNKNOWN, "Unknown")
        self.assertEqual(UNKNOWN_COPYRIGHTED, "UnknownCopyrighted")

        # Test that these constants are used correctly in modules
        import decopy.file_policy as file_policy_module

        # These should be available and working
        self.assertTrue(hasattr(file_policy_module, "UNKNOWN_COPYRIGHTED"))


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