from django.db import models
from django.contrib.gis.db import models as geomodels
from accounts.models import CustomUser, Device
from vehiclehub.models import VehicleType, Vehicle
import random

class Location(models.Model):
    name = models.CharField(max_length=100)
    latitude = models.FloatField()
    longitude = models.FloatField()

    def __str__(self):
        return self.name

class Ride(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('processing','Processing'),
        ('accepted', 'Accepted'),
        ('started', 'Started'),
        ('rejected', 'Rejected'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),

    )

    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='rides')
    driver = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='driver_rides',null=True)
    user_device = models.ForeignKey(Device, on_delete=models.SET_NULL, null=True, related_name='user_rides')
    vehicle_type = models.ForeignKey(VehicleType, on_delete=models.SET_NULL, null=True, related_name='rides')
    vehicle = models.ForeignKey(Vehicle, on_delete=models.SET_NULL, null=True, related_name='rides')
    pickup_location = geomodels.PointField(geography=True)
    dropoff_location = geomodels.PointField(geography=True)
    ride_time = models.DateTimeField()
    start_time  = models.DateTimeField(null=True)
    end_time  = models.DateTimeField(null=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    otp = models.CharField(max_length=4, blank=True)
    pickup_name = models.CharField(max_length=255, null=True, blank=True)
    dropoff_name = models.CharField(max_length=255, null=True, blank=True)
    distance = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    estimated_fare = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)

    def save(self, *args, **kwargs):
        if not self.otp:
            self.otp = ''.join([str(random.randint(0, 9)) for _ in range(4)])
        super(Ride, self).save(*args, **kwargs)

    def __str__(self):
        return f"{self.user.mobile_number} - {self.status}"

class DriverResponseLog(models.Model):
    ride = models.ForeignKey(Ride, on_delete=models.CASCADE, related_name='driver_responses')
    driver = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='driver_responses')
    response = models.CharField(max_length=50) # 'accepted' or 'rejected'
    reason = models.TextField(null=True, blank=True) # Reason for rejection
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.driver.mobile_number} - {self.response}"

class SharedRide(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('processing','Processing'),
        ('accepted', 'Accepted'),
        ('started', 'Started'),
        ('rejected', 'Rejected'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),
    )

    vehicle_type = models.ForeignKey(VehicleType, on_delete=models.SET_NULL, null=True, related_name='shared_rides')
    primary_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='initiated_shared_rides')
    primary_pickup_location = geomodels.PointField(geography=True)
    primary_dropoff_location = geomodels.PointField(geography=True)
    ride_time = models.DateTimeField()
    seats_total = models.PositiveIntegerField()
    seats_occupied = models.PositiveIntegerField(default=0)
    status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    pickup_name = models.CharField(max_length=255,null=True, blank=True)
    dropoff_name = models.CharField(max_length=255,null=True, blank=True)
    seats_required = models.PositiveIntegerField(default=0)
    user_device = models.ForeignKey(Device, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return f"{self.primary_user.mobile_number} - {self.status}"

class SharedRideParticipant(models.Model):
    shared_ride = models.ForeignKey(SharedRide, on_delete=models.CASCADE, related_name='participants')
    participant_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='shared_ride_participation')
    pickup_location = geomodels.PointField(geography=True)
    dropoff_location = geomodels.PointField(geography=True)
    pickup_name = models.CharField(max_length=255,null=True, blank=True)
    dropoff_name = models.CharField(max_length=255,null=True, blank=True)
    seats_required = models.PositiveIntegerField(default=0)
    device_token = models.ForeignKey(Device, on_delete=models.SET_NULL, null=True)
    joined_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.participant_user.mobile_number}"
    
class RoutePoint(models.Model):
    name = models.CharField(max_length=200)
    latitude = models.FloatField()
    longitude = models.FloatField()
    geomodels.PointField(geography=True)

    def __str__(self):
        return self.name

class Route(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    pickup_point = models.ForeignKey(RoutePoint, on_delete=models.CASCADE, related_name='routes_as_pickup')
    dropoff_point = models.ForeignKey(RoutePoint, on_delete=models.CASCADE, related_name='routes_as_dropoff')
    intermediate_points = models.ManyToManyField(RoutePoint, related_name='routes_as_intermediate')

    def __str__(self):
        return self.name

    def add_intermediate_point(self, point):
        if point not in self.intermediate_points.all():
            self.intermediate_points.add(point)

    def remove_intermediate_point(self, point):
        if point in self.intermediate_points.all():
            self.intermediate_points.remove(point)

class Sequence(models.Model):
    route = models.ForeignKey(Route, on_delete=models.CASCADE, related_name='sequences')
    point = models.ForeignKey(RoutePoint, on_delete=models.CASCADE, related_name='sequences')
    order = models.PositiveIntegerField()

    def __str__(self):
        return f"{self.point.name} - {self.order}"

class ScheduledRideMaster(models.Model):
    name = models.CharField(max_length=100)
    starting_time = models.TimeField()
    ending_time = models.TimeField()
    route = models.ForeignKey(Route, on_delete=models.SET_NULL, null=True)
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, null=True)
    assigned_at = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=15, choices=[('active', 'Active'), ('inactive', 'Inactive')], default='active')

    def __str__(self):
        return f"{self.name} - {self.starting_time} to {self.ending_time}"

class ScheduledRideDay(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('processing','Processing'),
        ('accepted', 'Accepted'),
        ('started', 'Started'),
        ('rejected', 'Rejected'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),
    )
    scheduled_ride = models.ForeignKey(ScheduledRideMaster, on_delete=models.CASCADE)
    status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='pending')
    date = models.DateField()
    total_seats = models.PositiveIntegerField()
    booked_seats = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.scheduled_ride.name} - {self.date}"

class ScheduledRideParticipant(models.Model):
    scheduled_ride_day = models.ForeignKey(ScheduledRideDay, on_delete=models.CASCADE)
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    join_point = geomodels.PointField(geography=True)
    end_point = geomodels.PointField(geography=True)
    seats_required = models.PositiveIntegerField(default=0)
    confirmed_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user.mobile_number} - {self.scheduled_ride_day.scheduled_ride.name}"