"""
Integration tests for park creation workflow.

These tests verify the complete workflow of park creation including
validation, location creation, and related operations.
"""

import pytest
from django.test import TestCase

from apps.parks.forms import ParkForm
from tests.factories import (
    OperatorCompanyFactory,
    ParkAreaFactory,
    ParkFactory,
    RideFactory,
    UserFactory,
)


@pytest.mark.django_db
class TestParkCreationWorkflow(TestCase):
    """Integration tests for complete park creation workflow."""

    def test__create_park_with_form__valid_data__creates_park_and_location(self):
        """Test creating a park with form creates both park and location."""
        operator = OperatorCompanyFactory()

        data = {
            "name": "New Test Park",
            "operator": operator.pk,
            "status": "OPERATING",
            "latitude": "37.123456",
            "longitude": "-122.654321",
            "city": "San Francisco",
            "state": "CA",
            "country": "USA",
        }

        form = ParkForm(data=data)

        if form.is_valid():
            park = form.save()

            # Verify park was created
            assert park.pk is not None
            assert park.name == "New Test Park"
            assert park.operator == operator

            # Verify location was created
            if park.location.exists():
                location = park.location.first()
                assert location.city == "San Francisco"
                assert location.country == "USA"

    def test__create_park__with_areas__creates_complete_structure(self):
        """Test creating a park with areas creates complete structure."""
        park = ParkFactory()

        # Add areas
        ParkAreaFactory(park=park, name="Main Entrance")
        ParkAreaFactory(park=park, name="Thrill Zone")
        ParkAreaFactory(park=park, name="Kids Area")

        # Verify structure
        assert park.areas.count() == 3
        assert park.areas.filter(name="Main Entrance").exists()
        assert park.areas.filter(name="Thrill Zone").exists()
        assert park.areas.filter(name="Kids Area").exists()

    def test__create_park__with_rides__updates_counts(self):
        """Test creating a park with rides updates ride counts."""
        park = ParkFactory()

        # Add rides
        RideFactory(park=park, category="RC")  # Roller coaster
        RideFactory(park=park, category="RC")  # Roller coaster
        RideFactory(park=park, category="TR")  # Thrill ride
        RideFactory(park=park, category="DR")  # Dark ride

        # Verify ride counts
        assert park.rides.count() == 4
        assert park.rides.filter(category="RC").count() == 2


@pytest.mark.django_db
class TestParkUpdateWorkflow(TestCase):
    """Integration tests for park update workflow."""

    def test__update_park__changes_status__updates_correctly(self):
        """Test updating park status updates correctly."""
        park = ParkFactory(status="OPERATING")

        # Update via FSM transition
        park.close_temporarily()

        park.refresh_from_db()
        assert park.status == "CLOSED_TEMP"

    def test__update_park_location__updates_location_record(self):
        """Test updating park location updates the location record."""
        park = ParkFactory()

        form_data = {
            "name": park.name,
            "operator": park.operator.pk,
            "status": park.status,
            "city": "New City",
            "state": "NY",
            "country": "USA",
        }

        form = ParkForm(instance=park, data=form_data)

        if form.is_valid():
            updated_park = form.save()

            # Verify location was updated
            if updated_park.location.exists():
                location = updated_park.location.first()
                assert location.city == "New City"


@pytest.mark.django_db
class TestParkReviewWorkflow(TestCase):
    """Integration tests for park review workflow."""

    def test__add_review__updates_park_rating(self):
        """Test adding a review affects park's average rating."""
        park = ParkFactory()
        user1 = UserFactory()
        user2 = UserFactory()

        # Add reviews
        from tests.factories import ParkReviewFactory

        ParkReviewFactory(park=park, user=user1, rating=8, is_published=True)
        ParkReviewFactory(park=park, user=user2, rating=10, is_published=True)

        # Calculate average
        avg = park.reviews.filter(is_published=True).values_list("rating", flat=True)
        calculated_avg = sum(avg) / len(avg)

        assert calculated_avg == 9.0

    def test__unpublish_review__excludes_from_rating(self):
        """Test unpublishing a review excludes it from rating calculation."""
        park = ParkFactory()
        user1 = UserFactory()
        user2 = UserFactory()

        from tests.factories import ParkReviewFactory

        ParkReviewFactory(park=park, user=user1, rating=10, is_published=True)
        review2 = ParkReviewFactory(park=park, user=user2, rating=2, is_published=True)

        # Unpublish the low rating
        review2.is_published = False
        review2.save()

        # Calculate average - should only include published reviews
        published_reviews = park.reviews.filter(is_published=True)
        assert published_reviews.count() == 1
        assert published_reviews.first().rating == 10


@pytest.mark.django_db
class TestParkAreaRideWorkflow(TestCase):
    """Integration tests for park area and ride workflow."""

    def test__add_ride_to_area__associates_correctly(self):
        """Test adding a ride to an area associates them correctly."""
        park = ParkFactory()
        area = ParkAreaFactory(park=park, name="Thrill Zone")

        ride = RideFactory(park=park, park_area=area, name="Super Coaster")

        assert ride.park_area == area
        assert ride in area.rides.all()

    def test__delete_area__handles_rides_correctly(self):
        """Test deleting an area handles associated rides."""
        park = ParkFactory()
        area = ParkAreaFactory(park=park)
        ride = RideFactory(park=park, park_area=area)

        ride_pk = ride.pk

        # Delete area - ride should have park_area set to NULL
        area.delete()

        ride.refresh_from_db()
        assert ride.park_area is None
        assert ride.pk == ride_pk  # Ride still exists


@pytest.mark.django_db
class TestParkOperatorWorkflow(TestCase):
    """Integration tests for park operator workflow."""

    def test__change_operator__updates_park(self):
        """Test changing park operator updates the relationship."""
        old_operator = OperatorCompanyFactory(name="Old Operator")
        new_operator = OperatorCompanyFactory(name="New Operator")
        park = ParkFactory(operator=old_operator)

        # Change operator
        park.operator = new_operator
        park.save()

        park.refresh_from_db()
        assert park.operator == new_operator
        assert park.operator.name == "New Operator"

    def test__operator_with_multiple_parks__lists_all_parks(self):
        """Test operator with multiple parks lists all parks."""
        operator = OperatorCompanyFactory()

        park1 = ParkFactory(operator=operator, name="Park One")
        park2 = ParkFactory(operator=operator, name="Park Two")
        park3 = ParkFactory(operator=operator, name="Park Three")

        # Verify operator's parks
        operator_parks = operator.operated_parks.all()
        assert operator_parks.count() == 3
        assert park1 in operator_parks
        assert park2 in operator_parks
        assert park3 in operator_parks
