import pghistory
from django.contrib.gis.db import models as gis_models
from django.contrib.gis.geos import Point
from django.db import models


@pghistory.track()
class RideLocation(models.Model):
    """
    Lightweight location tracking for individual rides within parks.
    Optional coordinates with focus on practical navigation information.
    """

    # Relationships
    ride = models.OneToOneField("rides.Ride", on_delete=models.CASCADE, related_name="ride_location")

    # Optional Spatial Data - keep it simple with single point
    point = gis_models.PointField(
        srid=4326,
        null=True,
        blank=True,
        help_text="Geographic coordinates for ride location (longitude, latitude)",
    )

    # Park Area Information
    park_area = models.CharField(
        max_length=100,
        blank=True,
        db_index=True,
        help_text=("Themed area or land within the park (e.g., 'Frontierland', 'Tomorrowland')"),
    )

    # General notes field to match database schema
    notes = models.TextField(blank=True, help_text="General location notes")

    # Navigation and Entrance Information
    entrance_notes = models.TextField(
        blank=True,
        help_text="Directions to ride entrance, queue location, or navigation tips",
    )

    # Accessibility Information
    accessibility_notes = models.TextField(
        blank=True,
        help_text="Information about accessible entrances, wheelchair access, etc.",
    )

    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    @property
    def latitude(self):
        """Return latitude from point field for backward compatibility."""
        if self.point:
            return self.point.y
        return None

    @property
    def longitude(self):
        """Return longitude from point field for backward compatibility."""
        if self.point:
            return self.point.x
        return None

    @property
    def coordinates(self):
        """Return (latitude, longitude) tuple."""
        if self.point:
            return (self.latitude, self.longitude)
        return (None, None)

    @property
    def has_coordinates(self):
        """Check if coordinates are set."""
        return self.point is not None

    def set_coordinates(self, latitude, longitude):
        """
        Set the location's point from latitude and longitude coordinates.
        Validates coordinate ranges.
        """
        if latitude is None or longitude is None:
            self.point = None
            return

        if not -90 <= latitude <= 90:
            raise ValueError("Latitude must be between -90 and 90.")
        if not -180 <= longitude <= 180:
            raise ValueError("Longitude must be between -180 and 180.")

        self.point = Point(longitude, latitude, srid=4326)

    def distance_to_park_location(self):
        """
        Calculate distance to parent park's location if both have coordinates.
        Returns distance in kilometers.
        """
        if not self.point:
            return None

        park_location = getattr(self.ride.park, "location", None)
        if not park_location or not park_location.point:
            return None

        # Use geodetic distance calculation which returns meters, convert to km
        distance_m = self.point.distance(park_location.point)
        return distance_m / 1000.0

    def __str__(self):
        area_str = f" in {self.park_area}" if self.park_area else ""
        return f"Location for {self.ride.name}{area_str}"

    class Meta:
        verbose_name = "Ride Location"
        verbose_name_plural = "Ride Locations"
        ordering = ["ride__name"]
        indexes = [
            models.Index(fields=["park_area"]),
            # Spatial index will be created automatically for PostGIS
            # PointField
        ]
