import os
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager,AbstractUser
from django.contrib.auth.models import Group
from .models import *
from django.core.validators import EmailValidator
from django.utils.timezone import now
from datetime import datetime
from django.utils import timezone

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('The email field must be set')
        email = self.normalize_email(email)
        user = self.model(email = email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(email, password, **extra_fields)   
     
def get_timestamped_filename(instance, image):

    base, extension = os.path.splitext("image")
    timestamp = now().strftime('%Y%m%d%H%M%S')
    new_filename = f"{base}_{timestamp}{extension}"
    return os.path.join("profile_image", new_filename)
    
class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)    #email = models.EmailField(unique=True, validators=[EmailValidator(message="Invalid email address")])
    first_name = models.CharField(max_length=30, null=True, blank=True)
    last_name = models.CharField(max_length=30, null=True, blank=True)
    profile_image = models.ImageField(upload_to=get_timestamped_filename, null=True, blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    phone_no = models.CharField(max_length=15,null=True,blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
   

    def get_full_name(self):
        return '{} {}'.format(self.email)

    def get_short_name(self):
        return self.email
    
class Person(models.Model):
    GENDER_CHOICES = [
        ('Male', 'Male'),
        ('Female', 'Female'),
        ('Other', 'Other'),
        ('Prefer not to say', 'Prefer not to say'),
    ]
    username = models.CharField(unique=True, max_length=30)
    first_name = models.CharField(max_length=30, null=True, blank=True)
    last_name = models.CharField(max_length=30, null=True, blank=True)
    contact_number = models.CharField(max_length=15, null=True, blank=True)
    email = models.EmailField(null=True, blank=True)
    profile_image = models.ImageField(upload_to='person/dp/', null=True, blank=True)
    gender = models.CharField(max_length=20, choices=GENDER_CHOICES, blank=True, null=True)
    dob = models.DateField(verbose_name="Date of Birth", null=True, blank=True)
    is_blacklisted = models.BooleanField(default=False)
    opt_out = models.BooleanField(default=False)
    entry_time = models.TimeField(null=True, blank=True)
    exit_time = models.TimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True,null=True, blank=True)

class FaceImage(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='face_images')
    image = models.ImageField(upload_to='face_images/') # Supported extention: .jpeg, .jpg, .jpe, .png, .gif, .bmp, .dib, .tiff, .tif, .ico, .webp
    uploaded_at = models.DateTimeField(auto_now_add=True)

class Organization(models.Model):
    organization_user = models.ManyToManyField(CustomUser)
    org_type = models.CharField(max_length=50,null= True, blank=True)
    org_name = models.CharField(max_length=50,unique=True, null=True, blank=True)
    org_address = models.CharField(max_length=50, null=True, blank=True)
    org_city = models.CharField(max_length=50, null=True, blank=True)
    org_state = models.CharField(max_length=50, null=True, blank=True)
    org_country = models.CharField(max_length=50, null=True, blank=True)
    org_zipcode = models.CharField(max_length=50, null=True, blank=True)
    org_phone = models.CharField(max_length=50, null=True, blank=True)
    org_email = models.EmailField(max_length=50, null=True, blank=True)
    email_notification_is_enabled = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='updated_by')
    updated_at = models.DateTimeField(auto_now=True)

class Location(models.Model):
    location_user = models.ManyToManyField(CustomUser)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, blank=True)
    loc_name = models.CharField(max_length=50,unique=False, null=True, blank=True)
    loc_address = models.CharField(max_length=50, null=True, blank=True)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='loc_created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='loc_updated_by')
    updated_at = models.DateTimeField(auto_now=True)
    
class Area(models.Model):
    area_user = models.ManyToManyField(CustomUser)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, blank=True)
    location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
    area_name = models.CharField(max_length=50,unique=False, null=True, blank=True)
    area_address = models.CharField(max_length=50, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='area_created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='area_updated_by')
    updated_at = models.DateTimeField(auto_now=True)

class Camera(models.Model):
    camera_user = models.ManyToManyField(CustomUser)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, blank=True)
    location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
    area = models.ForeignKey(Area, on_delete=models.CASCADE, null=True, blank=True)
    camera_name = models.CharField(max_length=100,unique=False, null=True, blank=True)
    fps = models.IntegerField(default= 30,null=True,blank=True)
    ip_address = models.CharField(max_length=100, null=True, blank=True)
    rtsp_url = models.CharField(max_length=1000, null=True, blank=True)
    frame_numbers = models.CharField(max_length=255, null=True, blank=True)
    port = models.IntegerField(null=True,blank=True)
    username = models.CharField(max_length=100, null=True, blank=True)
    password = models.CharField(max_length=100, null=True, blank=True)
    is_enabled = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='camera_created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='camera_updated_by')
    updated_at = models.DateTimeField(auto_now=True)
           
class CameraEvent(models.Model):
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, blank=True)
    location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
    area = models.ForeignKey(Area, on_delete=models.CASCADE, null=True, blank=True)
    camera = models.ForeignKey(Camera, on_delete=models.CASCADE, null=True, blank=True)
    camera_event = models.CharField(max_length=500, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    is_enabled = models.BooleanField(default=True)
    is_event_detect = models.BooleanField(default = True)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='camera_event_created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='camera_event_updated_by')
    updated_at = models.DateTimeField(auto_now=True)

class Alert(models.Model):
    DETECTION_CHOICES = [
        ('Yes', 'Yes'),
        ('No', 'No'),
        ('NotDetected', 'NotDetected')
    ]
    person = models.ForeignKey(Person, on_delete=models.SET_NULL, null=True, blank=True)
    camera = models.ForeignKey(Camera, on_delete=models.SET_NULL, null=True, blank=True)
    camera_events = models.ForeignKey(CameraEvent, on_delete=models.SET_NULL, null=True, blank=True)
    detection_choice = models.CharField(max_length=20, choices=DETECTION_CHOICES, blank=True, null=True)
    camera_incharge = models.ManyToManyField(CustomUser)
    organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, null=True, blank=True)
    area = models.ForeignKey(Area, on_delete=models.SET_NULL, null=True, blank=True)
    location = models.ForeignKey(Location, on_delete=models.SET_NULL, null=True, blank=True)
    is_event_detect = models.BooleanField(default = True)
    frame = models.ImageField(upload_to = 'alert_images/', null=True, blank=True)
    alert_message = models.CharField(max_length=1000, null=True, blank=True)
    is_enabled = models.BooleanField(default=True)
    created_at = models.DateTimeField(default=timezone.now)

class AlertPersonTracking(models.Model):
    tracking_id = models.IntegerField(null=True, blank=True)
    alerts = models.ManyToManyField(Alert)
    created_at = models.DateTimeField(default=timezone.now)

class Roi(models.Model):
    camera = models.ForeignKey(Camera, on_delete=models.CASCADE, null=True, blank=True)
    camera_events = models.ManyToManyField(CameraEvent)
    roi_name = models.CharField(max_length=200,null=True, blank=True)
    frame_number = models.IntegerField(null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    # Using simple (x, y) coordinates for the top-left and bottom-right corners of the ROI rectangle
    coordinates = models.JSONField(default=dict, null=True, blank=True) # {"coordiantes":[[12,33],[324,346]]}
    start_time = models.TimeField(null=True, blank=True)
    end_time = models.TimeField(null=True, blank=True)
    color = models.CharField(max_length=500, default="#00ff00", null=True, blank=True)  # Default color is green
    priority = models.PositiveIntegerField(default=1,null=True, blank=True) # 1, 2, 3... where 1 is the highest priority
    specific_analytics = models.BooleanField(default=False,null=True, blank=True)  # Example: Only apply facial recognition in this ROI
    created_at = models.DateTimeField(default=timezone.now)
    created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='roi_created_by')
    updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='roi_updated_by')
    updated_at = models.DateTimeField(auto_now=True)

class QueueManagement(models.Model):
    roi = models.ForeignKey(Roi, on_delete=models.CASCADE, null=True, blank=True)
    # camera = models.ForeignKey(Camera, on_delete=models.CASCADE, null=True, blank=True)
    # camera_events = models.ManyToManyField(CameraEvent)
    currunt_queue_count = models.IntegerField(null=True, blank=True)
    average_waiting_time = models.IntegerField(null=True, blank=True)
    recomanded_staff_adjustment = models.CharField(max_length=200,null=True, blank=True)
    action = models.CharField(max_length=200, null=True, blank=True)
    created_at = models.DateTimeField(default=timezone.now)

class HeatMapping(models.Model):
    roi = models.ForeignKey(Roi, on_delete=models.CASCADE, null=True, blank=True)
    dwel_time = models.JSONField(null=True)
    created_at = models.DateTimeField(default=timezone.now)
    
class DemographicDetails(models.Model):
    roi = models.ForeignKey(Roi, on_delete=models.CASCADE, null=True, blank=True)
    age_range = models.CharField(max_length=200, null=True, blank=True)
    unique_user = models.CharField(max_length=200, null=True, blank=True)
    total_Events = models.IntegerField(null=True, blank=True)
    average_age = models.IntegerField(null=True, blank=True)
    median_age = models.IntegerField(null=True, blank=True)
    mode_age = models.IntegerField(null=True, blank=True)
    created_at = models.DateTimeField(default=timezone.now)

class Parking(models.Model):
    roi = models.ForeignKey(Roi, on_delete=models.CASCADE, null=True, blank=True)
    total_count = models.IntegerField(null=True, blank=True)
    occupied_parking = models.IntegerField(null=True, blank=True)
    created_at = models.DateTimeField(default=timezone.now)

class LinkCameraEventToCamera(models.Model):
    camera_events = models.ManyToManyField(CameraEvent)
    camera = models.ForeignKey(Camera, on_delete=models.CASCADE)
    is_enabled = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

class TelegramBotToken(models.Model):
    MESSENGER_CHOICES = (
        ('Telegram', 'Telegram'),
        ('Whatsapp', 'Whatsapp'),
    )
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE,null=True,blank=True)
    messenger_type = models.CharField(max_length=100, choices = MESSENGER_CHOICES, default='Telegram',null=True,blank=True)
    chat_id = models.CharField(max_length=1000, null=True, blank=True)
    bot_token = models.CharField(max_length=1000, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_enabled = models.BooleanField(default=True)


class DashboardRetail(models.Model):
    name = models.CharField(max_length=1000, null=True, blank=True)

class DashboardManufacturing(models.Model):
    name = models.CharField(max_length=1000, null=True, blank=True)

class SafetyAndCompliance(models.Model):
    name = models.CharField(max_length=1000, null=True, blank=True)