from django.test import TestCase
from django.contrib.auth.models import User
from rest_framework.test import APIClient
from .models import PropertyType, PropertyTypeBed, Property
from structures.models import Structure


class PropertyTypeSerializerTestCase(TestCase):
    """Test suite for PropertyType serializer num_beds field."""

    def setUp(self):
        """Create test fixtures."""
        self.user = User.objects.create_user(username="testuser", password="pass123")
        self.structure = Structure.objects.create(
            user=self.user,
            name="Test Structure",
            istat_code="TEST001",
        )
        self.client = APIClient()

    def test_serializer_returns_num_beds(self):
        """Test that PropertyTypeSerializer includes num_beds in response."""
        property_type = PropertyType.objects.create(
            structure=self.structure,
            name="Deluxe Suite",
            max_guests=4,
            num_beds=2,
            num_sofa_beds=1,
        )
        PropertyTypeBed.objects.create(
            property_type=property_type,
            bed_type="Queen",
            quantity=2,
        )

        from .serializers import PropertyTypeSerializer
        serializer = PropertyTypeSerializer(property_type)
        data = serializer.data

        self.assertIn("num_beds", data)
        self.assertEqual(data["num_beds"], 2)
        self.assertEqual(data["num_sofa_beds"], 1)
        self.assertEqual(data["max_guests"], 4)

    def test_serializer_accepts_num_beds_on_create(self):
        """Test that PropertyTypeSerializer accepts num_beds on creation."""
        from .serializers import PropertyTypeSerializer

        data = {
            "structure": self.structure.id,
            "name": "Standard Room",
            "max_guests": 2,
            "num_beds": 1,
            "num_sofa_beds": 0,
            "num_bedrooms": 1,
            "num_bathrooms": 1,
            "amenities": "WiFi, TV",
            "beds": [
                {"bed_type": "Single", "quantity": 1}
            ],
        }

        serializer = PropertyTypeSerializer(data=data, context={"request": None})
        self.assertTrue(serializer.is_valid(), serializer.errors)
        property_type = serializer.save()

        self.assertEqual(property_type.num_beds, 1)
        self.assertEqual(property_type.name, "Standard Room")

    def test_serializer_accepts_num_beds_on_update(self):
        """Test that PropertyTypeSerializer accepts num_beds on update."""
        from .serializers import PropertyTypeSerializer

        property_type = PropertyType.objects.create(
            structure=self.structure,
            name="Standard Room",
            max_guests=2,
            num_beds=1,
        )
        PropertyTypeBed.objects.create(
            property_type=property_type,
            bed_type="Single",
            quantity=1,
        )

        data = {
            "structure": self.structure.id,
            "name": "Upgraded Room",
            "max_guests": 4,
            "num_beds": 2,
            "num_sofa_beds": 1,
            "num_bedrooms": 1,
            "num_bathrooms": 1,
            "amenities": "WiFi, TV",
            "beds": [
                {"bed_type": "Double", "quantity": 1}
            ],
        }

        serializer = PropertyTypeSerializer(
            property_type,
            data=data,
            context={"request": None}
        )
        self.assertTrue(serializer.is_valid(), serializer.errors)
        updated = serializer.save()

        self.assertEqual(updated.num_beds, 2)
        self.assertEqual(updated.num_sofa_beds, 1)

    def test_serializer_validates_negative_num_beds(self):
        """Test that PropertyTypeSerializer rejects negative num_beds."""
        from .serializers import PropertyTypeSerializer

        data = {
            "structure": self.structure.id,
            "name": "Invalid Room",
            "max_guests": 2,
            "num_beds": -1,  # Invalid
            "num_sofa_beds": 0,
            "num_bedrooms": 1,
            "num_bathrooms": 1,
            "beds": [
                {"bed_type": "Single", "quantity": 1}
            ],
        }

        serializer = PropertyTypeSerializer(data=data, context={"request": None})
        self.assertFalse(serializer.is_valid())
        self.assertIn("num_beds", serializer.errors)
        self.assertIn("non-negative", str(serializer.errors["num_beds"]))

    def test_serializer_validates_negative_num_sofa_beds(self):
        """Test that PropertyTypeSerializer validates num_sofa_beds."""
        from .serializers import PropertyTypeSerializer

        data = {
            "structure": self.structure.id,
            "name": "Invalid Room",
            "max_guests": 2,
            "num_beds": 1,
            "num_sofa_beds": -5,  # Invalid
            "num_bedrooms": 1,
            "num_bathrooms": 1,
            "beds": [
                {"bed_type": "Single", "quantity": 1}
            ],
        }

        serializer = PropertyTypeSerializer(data=data, context={"request": None})
        self.assertFalse(serializer.is_valid())
        self.assertIn("num_sofa_beds", serializer.errors)

    def test_serializer_preserves_beds_relation(self):
        """Test that beds relation is preserved and not affected by num_beds changes."""
        from .serializers import PropertyTypeSerializer

        property_type = PropertyType.objects.create(
            structure=self.structure,
            name="Standard Room",
            max_guests=2,
            num_beds=1,
        )
        bed1 = PropertyTypeBed.objects.create(
            property_type=property_type,
            bed_type="Single",
            quantity=1,
        )
        bed2 = PropertyTypeBed.objects.create(
            property_type=property_type,
            bed_type="Extra Single",
            quantity=1,
        )

        serializer = PropertyTypeSerializer(property_type)
        data = serializer.data

        # Check beds relation is intact
        self.assertIn("beds", data)
        self.assertEqual(len(data["beds"]), 2)
        bed_types = [bed["bed_type"] for bed in data["beds"]]
        self.assertIn("Single", bed_types)
        self.assertIn("Extra Single", bed_types)

    def test_zero_beds_allowed(self):
        """Test that zero beds is a valid value."""
        from .serializers import PropertyTypeSerializer

        data = {
            "structure": self.structure.id,
            "name": "Activity Space",
            "max_guests": 0,
            "num_beds": 0,  # Zero is allowed
            "num_sofa_beds": 0,
            "num_bedrooms": 0,
            "num_bathrooms": 1,
            "beds": [
                {"bed_type": "N/A", "quantity": 0}
            ],
        }

        serializer = PropertyTypeSerializer(data=data, context={"request": None})
        self.assertTrue(serializer.is_valid(), serializer.errors)
        property_type = serializer.save()

        self.assertEqual(property_type.num_beds, 0)

    def test_large_num_beds_accepted(self):
        """Test that large num_beds values are accepted."""
        from .serializers import PropertyTypeSerializer

        data = {
            "structure": self.structure.id,
            "name": "Large Dormitory",
            "max_guests": 50,
            "num_beds": 50,  # Large value
            "num_sofa_beds": 0,
            "num_bedrooms": 5,
            "num_bathrooms": 5,
            "beds": [
                {"bed_type": "Single", "quantity": 50}
            ],
        }

        serializer = PropertyTypeSerializer(data=data, context={"request": None})
        self.assertTrue(serializer.is_valid(), serializer.errors)
        property_type = serializer.save()

        self.assertEqual(property_type.num_beds, 50)

