#!/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.

"""Tests for License class extraction to core_types.py"""

import unittest

import debian.copyright as dc

try:
    from decopy.core_types import License
except ImportError as e:
    msg = "Cannot import License from core_types module"
    raise ImportError(msg) from e


class TestLicenseClass(unittest.TestCase):
    """Test License class functionality in core_types module"""

    def setUp(self):
        """Set up test fixtures"""
        License.licenses = {}

    def test_license_creation(self):
        """Test License class can be created with a name"""
        license_ = License("MIT")
        self.assertIsNotNone(license_)
        self.assertEqual(license_.name, "MIT")
        self.assertIsInstance(license_.name, str)
        self.assertIsInstance(license_, License)

    def test_license_string_representation(self):
        """str(License) is the bare identity (its name).

        Rendering the DEP-5 stanza is the output layer's job
        (renderer.Dep5Renderer.license_block), not the License value type's.
        """
        license_ = License("MIT")
        self.assertEqual(str(license_), "MIT")

    def test_license_static_get_method(self):
        """Test License static get method (singleton pattern)"""
        # Test creating a new license
        license1 = License.get("GPL")
        self.assertEqual(license1.name, "GPL")

        # Test getting the same license instance (singleton pattern)
        license2 = License.get("GPL")
        self.assertIs(license1, license2, "Same license instance should be returned")

        # Test different license
        license3 = License.get("Apache")
        self.assertEqual(license3.name, "Apache")
        self.assertIsNot(
            license1,
            license3,
            "Different licenses should be different instances",
        )

    def test_license_class_attributes(self):
        """Test License class has expected attributes and class variable"""
        # Test that the class has the licenses dictionary
        self.assertTrue(
            hasattr(License, "licenses"),
            "Should have licenses class variable",
        )
        self.assertIsInstance(License.licenses, dict, "licenses should be a dictionary")

        # Initially the licenses dict should be empty
        self.assertEqual(
            len(License.licenses),
            0,
            "Initial licenses dict should be empty",
        )

        # Test that licenses are stored in the class variable when created
        license1 = License.get("MIT")
        self.assertEqual(
            len(License.licenses),
            1,
            "Should have one license after creation",
        )
        self.assertIn("MIT", License.licenses, "MIT should be in licenses dict")
        self.assertIs(License.licenses["MIT"], license1, "Should be the same instance")

    def test_license_name_property(self):
        """Test License name property works correctly"""
        license_ = License("BSD-3-Clause")
        self.assertEqual(license_.name, "BSD-3-Clause")

        # Test that name can be accessed but not modified (no setter in __slots__)
        # Since name is in __slots__, it can be assigned but not property-set
        _original_name = license_.name
        license_.name = (
            "New Name"  # This works because it's in __slots__, not a property
        )
        self.assertEqual(license_.name, "New Name")

    def test_multiple_license_instances(self):
        """Test creating multiple license instances"""
        licenses = [
            License.get("MIT"),
            License.get("GPL"),
            License.get("Apache"),
            License.get("BSD"),
        ]

        # All should be different instances with different names
        names = [lic.name for lic in licenses]
        self.assertEqual(len(set(names)), 4)  # All names should be unique
        self.assertEqual(names, ["MIT", "GPL", "Apache", "BSD"])

    def test_license_stored_preserved_after_construction(self):
        """Direct License() construction must not reset stored on a cached License.

        Regression: __new__ returning a cached instance combined with __init__
        always resetting stored causes License("MIT") to silently wipe the stored
        paragraph that copyright_processor.py previously assigned.
        """
        dummy_license = dc.License(
            synopsis="MIT",
            text="some license paragraph content",
        )
        dummy_license_paragraph = dc.LicenseParagraph.create(dummy_license)
        license_ = License.get("MIT")
        license_.stored = dummy_license_paragraph

        # A direct constructor call with an already-cached name must not corrupt
        # the cached instance's stored attribute.
        _ = License("MIT")

        self.assertEqual(
            License.licenses["MIT"].stored,
            dummy_license_paragraph,
        )

    def test_license_get_stored_preserved(self):
        """License.get() must never reset stored on an already-cached License."""
        dummy_license = dc.License(
            synopsis="MIT",
            text="some license paragraph content",
        )
        dummy_license_paragraph = dc.LicenseParagraph.create(dummy_license)
        license_ = License.get("MIT")
        license_.stored = dummy_license_paragraph

        license2 = License.get("MIT")

        self.assertIs(license_, license2)
        self.assertEqual(license2.stored, dummy_license_paragraph)


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