#!/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
from decopy.dep5doc import dep5, output
from decopy.dep5doc.renderer import renderer_for
from decopy.fstree import 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.common.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.read_copyright(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, renderer_for(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 cmdoptions  # noqa: F401
        from decopy.common import (
            core_types,  # noqa: F401
            re_types,  # noqa: F401
        )

        # Test that core_types classes are available
        from decopy.common.core_types import (
            CopyrightHolder,
            License,
            Options,
            YearRange,
        )
        from decopy.dep5doc import (
            dep5,  # noqa: F401
            output,  # noqa: F401
        )
        from decopy.fstree import tree  # noqa: F401
        from decopy.licensing import (
            licenses,  # noqa: F401
            res,
        )

        # Test basic functionality of all imported classes
        license_obj = License("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.common.core_types",
            "decopy.dep5doc.dep5",
            "decopy.licensing.licenses",
            "decopy.dep5doc.output",
            "decopy.common.re_types",
            "decopy.licensing.res",
            "decopy.fstree.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.common.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.grouping.file_policy as file_policy_module

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


class TestExplainOption(unittest.TestCase):
    """Test that --explain parses into Options.explain."""

    def test_explain_flag_sets_true(self):
        options = cmdoptions.process_options(["--explain"])
        self.assertTrue(options.explain)

    def test_explain_default_false(self):
        options = cmdoptions.process_options([])
        self.assertFalse(options.explain)


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